From b58fac9a97bc2cb7256b9ae37dfb82a352e6f85e Mon Sep 17 00:00:00 2001 From: nobu Date: Sun, 24 Jan 2016 07:55:05 +0000 Subject: wait readable/writable * ext/io/wait/wait.c (io_wait_readwrite): [EXPERIMENTAL] allow to wait for multiple modes, readable and writable, at once. the arguments may change in the future. [Feature #12013] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53642 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/io/wait/wait.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 3 deletions(-) (limited to 'ext') diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c index 99435460d4..f7a7508eeb 100644 --- a/ext/io/wait/wait.c +++ b/ext/io/wait/wait.c @@ -117,8 +117,6 @@ io_ready_p(VALUE io) /* * call-seq: - * io.wait -> IO, true or nil - * io.wait(timeout) -> IO, true or nil * io.wait_readable -> IO, true or nil * io.wait_readable(timeout) -> IO, true or nil * @@ -168,6 +166,79 @@ io_wait_writable(int argc, VALUE *argv, VALUE io) return Qnil; } +static int +wait_mode_sym(VALUE mode) +{ + if (mode == ID2SYM(rb_intern("r"))) { + return RB_WAITFD_IN; + } + if (mode == ID2SYM(rb_intern("read"))) { + return RB_WAITFD_IN; + } + if (mode == ID2SYM(rb_intern("readable"))) { + return RB_WAITFD_IN; + } + if (mode == ID2SYM(rb_intern("w"))) { + return RB_WAITFD_OUT; + } + if (mode == ID2SYM(rb_intern("write"))) { + return RB_WAITFD_OUT; + } + if (mode == ID2SYM(rb_intern("writable"))) { + return RB_WAITFD_OUT; + } + if (mode == ID2SYM(rb_intern("rw"))) { + return RB_WAITFD_IN|RB_WAITFD_OUT; + } + if (mode == ID2SYM(rb_intern("read_write"))) { + return RB_WAITFD_IN|RB_WAITFD_OUT; + } + if (mode == ID2SYM(rb_intern("readable_writable"))) { + return RB_WAITFD_IN|RB_WAITFD_OUT; + } + rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode); + return 0; +} + +/* + * call-seq: + * io.wait(timeout = nil, mode = :read) -> IO, true or nil + * + * Waits until IO is readable or writable without blocking and returns + * +self+, or +nil+ when times out. + * Returns +true+ immediately when buffered data is available. + * Optional parameter +mode+ is one of +:read+, +:write+, or + * +:read_write+. + */ + +static VALUE +io_wait_readwrite(int argc, VALUE *argv, VALUE io) +{ + rb_io_t *fptr; + struct timeval timerec; + struct timeval *tv = NULL; + int event = 0; + int i; + + GetOpenFile(io, fptr); + for (i = 0; i < argc; ++i) { + if (SYMBOL_P(argv[i])) { + event |= wait_mode_sym(argv[i]); + } + else { + *(tv = &timerec) = rb_time_interval(argv[i]); + } + } + /* rb_time_interval() and might_mode() might convert the argument */ + rb_io_check_closed(fptr); + if (!event) event = RB_WAITFD_IN; + if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr)) + return Qtrue; + if (wait_for_single_fd(fptr, event, tv)) + return io; + return Qnil; +} + /* * IO wait methods */ @@ -177,7 +248,7 @@ Init_wait(void) { rb_define_method(rb_cIO, "nread", io_nread, 0); rb_define_method(rb_cIO, "ready?", io_ready_p, 0); - rb_define_method(rb_cIO, "wait", io_wait_readable, -1); + rb_define_method(rb_cIO, "wait", io_wait_readwrite, -1); rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1); rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1); } -- cgit v1.2.3