summaryrefslogtreecommitdiff
path: root/ext/io
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-01-24 07:55:05 (GMT)
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-01-24 07:55:05 (GMT)
commitb58fac9a97bc2cb7256b9ae37dfb82a352e6f85e (patch)
treec5bbc6f01381965bd8a21085b56773345b7779bb /ext/io
parent57752a2503525676e3d21f998cb8bb8357a02242 (diff)
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
Diffstat (limited to 'ext/io')
-rw-r--r--ext/io/wait/wait.c77
1 files changed, 74 insertions, 3 deletions
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 9943546..f7a7508 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);
}