[ruby/io-console] Fixed "Rework console to use rb_io_wait."

* Fixed backward compatibility.
* Added missing `rb_scheduler_timeout` declaration.

https://github.com/ruby/io-console/commit/813806079f
This commit is contained in:
Nobuyoshi Nakada 2020-10-10 15:15:21 +09:00
parent bfc1c7205d
commit b59640e155
No known key found for this signature in database
GPG Key ID: 7CD2805BFA3770C6
2 changed files with 53 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* -*- c-file-style: "ruby" -*- */ /* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
/* /*
* console IO module * console IO module
*/ */
@ -80,6 +80,10 @@ static ID id_getc, id_console, id_close, id_min, id_time, id_intr;
static ID id_gets; static ID id_gets;
#endif #endif
#ifdef HAVE_RB_SCHEDULER_TIMEOUT
extern VALUE rb_scheduler_timeout(struct timeval *timeout);
#endif
#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv) #define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv)
#ifndef HAVE_RB_F_SEND #ifndef HAVE_RB_F_SEND
@ -510,47 +514,63 @@ console_getch(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr; rb_io_t *fptr;
VALUE str; VALUE str;
wint_t c; wint_t c;
int w, len; int len;
char buf[8]; char buf[8];
wint_t wbuf[2]; wint_t wbuf[2];
# ifndef HAVE_RB_IO_WAIT
struct timeval *to = NULL, tv;
# else
VALUE timeout = Qnil; VALUE timeout = Qnil;
# endif
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (optp) { if (optp) {
if (optp->vtime) { if (optp->vtime) {
struct timeval tv; # ifndef HAVE_RB_IO_WAIT
tv.tv_sec = optp->vtime / 10; to = &tv;
tv.tv_usec = (optp->vtime % 10) * 100000; # else
timeout = rb_scheduler_timeout(&tv); struct timeval tv;
} # endif
if (optp->vmin != 1) { tv.tv_sec = optp->vtime / 10;
rb_warning("min option ignored"); tv.tv_usec = (optp->vtime % 10) * 100000;
} # ifdef HAVE_RB_IO_WAIT
if (optp->intr) { timeout = rb_scheduler_timeout(&tv);
VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout)); # endif
if (result == Qfalse) return Qnil; }
} if (optp->vmin != 1) {
else { rb_warning("min option ignored");
rb_warning("vtime option ignored if intr flag is unset"); }
} if (optp->intr) {
# ifndef HAVE_RB_IO_WAIT
int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
if (w < 0) rb_eof_error();
if (!(w & RB_WAITFD_IN)) return Qnil;
# else
VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout));
if (result == Qfalse) return Qnil;
# endif
}
else {
rb_warning("vtime option ignored if intr flag is unset");
}
} }
len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0); len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
switch (len) { switch (len) {
case 0: case 0:
return Qnil; return Qnil;
case 2: case 2:
buf[0] = (char)wbuf[0]; buf[0] = (char)wbuf[0];
c = wbuf[1]; c = wbuf[1];
len = 1; len = 1;
do { do {
buf[len++] = (unsigned char)c; buf[len++] = (unsigned char)c;
} while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
return rb_str_new(buf, len); return rb_str_new(buf, len);
default: default:
c = wbuf[0]; c = wbuf[0];
len = rb_uv_to_utf8(buf, c); len = rb_uv_to_utf8(buf, c);
str = rb_utf8_str_new(buf, len); str = rb_utf8_str_new(buf, len);
return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
} }
#endif #endif
} }

View File

@ -24,6 +24,9 @@ when true
# rb_funcallv: 2.1.0 # rb_funcallv: 2.1.0
# RARRAY_CONST_PTR: 2.1.0 # RARRAY_CONST_PTR: 2.1.0
# rb_sym2str: 2.2.0 # rb_sym2str: 2.2.0
if have_func("rb_scheduler_timeout")
have_func("rb_io_wait")
end
$defs << "-D""ENABLE_IO_GETPASS=1" $defs << "-D""ENABLE_IO_GETPASS=1"
create_makefile("io/console") {|conf| create_makefile("io/console") {|conf|
conf << "\n""VK_HEADER = #{vk_header}\n" conf << "\n""VK_HEADER = #{vk_header}\n"