From e9297f10ca549563c7142629136fbca167c76dba Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 14 Sep 2020 12:17:11 +1200 Subject: [PATCH 1/2] Rework console to use `rb_io_wait`. --- ext/io/console/console.c | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 64f795d..76253ee 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -513,44 +513,44 @@ console_getch(int argc, VALUE *argv, VALUE io) int w, len; char buf[8]; wint_t wbuf[2]; - struct timeval *to = NULL, tv; + VALUE timeout = Qnil; GetOpenFile(io, fptr); if (optp) { - if (optp->vtime) { - to = &tv; - tv.tv_sec = optp->vtime / 10; - tv.tv_usec = (optp->vtime % 10) * 100000; - } - if (optp->vmin != 1) { - rb_warning("min option ignored"); - } - if (optp->intr) { - 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 { - rb_warning("vtime option ignored if intr flag is unset"); - } + if (optp->vtime) { + struct timeval tv; + tv.tv_sec = optp->vtime / 10; + tv.tv_usec = (optp->vtime % 10) * 100000; + timeout = rb_scheduler_timeout(&tv); + } + if (optp->vmin != 1) { + rb_warning("min option ignored"); + } + if (optp->intr) { + VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout)); + if (result == Qfalse) return Qnil; + } + 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); switch (len) { case 0: - return Qnil; + return Qnil; case 2: - buf[0] = (char)wbuf[0]; - c = wbuf[1]; - len = 1; - do { - buf[len++] = (unsigned char)c; - } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); - return rb_str_new(buf, len); + buf[0] = (char)wbuf[0]; + c = wbuf[1]; + len = 1; + do { + buf[len++] = (unsigned char)c; + } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); + return rb_str_new(buf, len); default: - c = wbuf[0]; - len = rb_uv_to_utf8(buf, c); - str = rb_utf8_str_new(buf, len); - return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); + c = wbuf[0]; + len = rb_uv_to_utf8(buf, c); + str = rb_utf8_str_new(buf, len); + return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); } #endif } From 813806079f035b6f78c0bb0a14b410ae7837869a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 10 Oct 2020 15:15:21 +0900 Subject: [PATCH 2/2] Fixed "Rework console to use `rb_io_wait`." * Fixed backward compatibility. * Added missing `rb_scheduler_timeout` declaration. --- ext/io/console/console.c | 80 ++++++++++++++++++++++++--------------- ext/io/console/extconf.rb | 3 ++ 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 76253ee..50baf4f 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -1,4 +1,4 @@ -/* -*- c-file-style: "ruby" -*- */ +/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */ /* * 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; #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) #ifndef HAVE_RB_F_SEND @@ -510,47 +514,63 @@ console_getch(int argc, VALUE *argv, VALUE io) rb_io_t *fptr; VALUE str; wint_t c; - int w, len; + int len; char buf[8]; wint_t wbuf[2]; +# ifndef HAVE_RB_IO_WAIT + struct timeval *to = NULL, tv; +# else VALUE timeout = Qnil; +# endif GetOpenFile(io, fptr); if (optp) { - if (optp->vtime) { - struct timeval tv; - tv.tv_sec = optp->vtime / 10; - tv.tv_usec = (optp->vtime % 10) * 100000; - timeout = rb_scheduler_timeout(&tv); - } - if (optp->vmin != 1) { - rb_warning("min option ignored"); - } - if (optp->intr) { - VALUE result = RB_NUM2INT(rb_io_wait(io, RUBY_IO_READABLE, timeout)); - if (result == Qfalse) return Qnil; - } - else { - rb_warning("vtime option ignored if intr flag is unset"); - } + if (optp->vtime) { +# ifndef HAVE_RB_IO_WAIT + to = &tv; +# else + struct timeval tv; +# endif + tv.tv_sec = optp->vtime / 10; + tv.tv_usec = (optp->vtime % 10) * 100000; +# ifdef HAVE_RB_IO_WAIT + timeout = rb_scheduler_timeout(&tv); +# endif + } + if (optp->vmin != 1) { + rb_warning("min option ignored"); + } + 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); switch (len) { case 0: - return Qnil; + return Qnil; case 2: - buf[0] = (char)wbuf[0]; - c = wbuf[1]; - len = 1; - do { - buf[len++] = (unsigned char)c; - } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); - return rb_str_new(buf, len); + buf[0] = (char)wbuf[0]; + c = wbuf[1]; + len = 1; + do { + buf[len++] = (unsigned char)c; + } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); + return rb_str_new(buf, len); default: - c = wbuf[0]; - len = rb_uv_to_utf8(buf, c); - str = rb_utf8_str_new(buf, len); - return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); + c = wbuf[0]; + len = rb_uv_to_utf8(buf, c); + str = rb_utf8_str_new(buf, len); + return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); } #endif } diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb index 3d7e75e..3efdd6e 100644 --- a/ext/io/console/extconf.rb +++ b/ext/io/console/extconf.rb @@ -24,6 +24,9 @@ # rb_funcallv: 2.1.0 # RARRAY_CONST_PTR: 2.1.0 # rb_sym2str: 2.2.0 + if have_func("rb_scheduler_timeout") + have_func("rb_io_wait") + end $defs << "-D""ENABLE_IO_GETPASS=1" create_makefile("io/console") {|conf| conf << "\n""VK_HEADER = #{vk_header}\n"