ext/kgio/wait.c in kgio-2.4.2 vs ext/kgio/wait.c in kgio-2.5.0
- old
+ new
@@ -1,55 +1,95 @@
#include "kgio.h"
-
+#include "my_fileno.h"
static ID id_wait_rd, id_wait_wr;
-/*
- * avoiding rb_thread_select() or similar since rb_io_wait_*able can be
- * made to use poll() later on. It's highly unlikely Ruby will move to
- * use an edge-triggered event notification, so assigning EAGAIN is
- * probably safe...
- */
+#if defined(HAVE_RB_TIME_INTERVAL) && defined(HAVE_RB_WAIT_FOR_SINGLE_FD)
+static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
+{
+ struct timeval tv = rb_time_interval(timeout);
+ int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;
+ return rb_wait_for_single_fd(my_fileno(self), events, &tv);
+}
+#else /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
+static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
+{
+ VALUE argv[4];
+ VALUE set = rb_ary_new3(1, self);
+ argv[0] = write_p ? Qnil : set;
+ argv[1] = write_p ? set : Qnil;
+ argv[2] = Qnil;
+ argv[3] = timeout;
+
+ set = rb_funcall2(rb_cIO, rb_intern("select"), 4, argv);
+ return NIL_P(set) ? 0 : 1;
+}
+#endif /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
+
+static int kgio_wait(int argc, VALUE *argv, VALUE self, int write_p)
+{
+ int fd;
+ VALUE timeout;
+
+ if (rb_scan_args(argc, argv, "01", &timeout) == 1 && !NIL_P(timeout))
+ return kgio_timedwait(self, timeout, write_p);
+
+ fd = my_fileno(self);
+ errno = EAGAIN;
+ write_p ? rb_io_wait_writable(fd) : rb_io_wait_readable(fd);
+ return 1;
+}
+
/*
- * Blocks the running Thread indefinitely until +self+ IO object is readable.
- * This method is automatically called by default whenever kgio_read needs
- * to block on input.
+ * call-seq:
*
+ * io.kgio_wait_readable -> IO
+ * io.kgio_wait_readable(timeout) -> IO or nil
+ *
+ * Blocks the running Thread indefinitely until the IO object is readable
+ * or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
+ * is returned.
+ *
+ * This method is automatically called (without timeout argument) by default
+ * whenever kgio_read needs to block on input.
+ *
* Users of alternative threading/fiber libraries are
* encouraged to override this method in their subclasses or modules to
* work with their threading/blocking methods.
*/
-static VALUE kgio_wait_readable(VALUE self)
+static VALUE kgio_wait_readable(int argc, VALUE *argv, VALUE self)
{
- int fd = my_fileno(self);
+ int r = kgio_wait(argc, argv, self, 0);
- errno = EAGAIN;
- if (!rb_io_wait_readable(fd))
- rb_sys_fail("kgio_wait_readable");
-
- return self;
+ if (r < 0) rb_sys_fail("kgio_wait_readable");
+ return r == 0 ? Qnil : self;
}
/*
- * Blocks the running Thread indefinitely until +self+ IO object is writable.
- * This method is automatically called whenever kgio_write needs to
- * block on output.
+ * call-seq:
*
+ * io.kgio_wait_writeable -> IO
+ * io.kgio_wait_writable(timeout) -> IO or nil
+ *
+ * Blocks the running Thread indefinitely until the IO object is writable
+ * or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
+ * is returned.
+ *
+ * This method is automatically called (without timeout argument) by default
+ * whenever kgio_write needs to block on output.
+ *
* Users of alternative threading/fiber libraries are
* encouraged to override this method in their subclasses or modules to
* work with their threading/blocking methods.
*/
-static VALUE kgio_wait_writable(VALUE self)
+static VALUE kgio_wait_writable(int argc, VALUE *argv, VALUE self)
{
- int fd = my_fileno(self);
+ int r = kgio_wait(argc, argv, self, 1);
- errno = EAGAIN;
- if (!rb_io_wait_writable(fd))
- rb_sys_fail("kgio_wait_writable");
-
- return self;
+ if (r < 0) rb_sys_fail("kgio_wait_writable");
+ return r == 0 ? Qnil : self;
}
VALUE kgio_call_wait_writable(VALUE io)
{
return rb_funcall(io, id_wait_wr, 0, 0);
@@ -78,9 +118,9 @@
id_wait_rd = rb_intern("kgio_wait_readable");
id_wait_wr = rb_intern("kgio_wait_writable");
rb_define_method(mWaiters, "kgio_wait_readable",
- kgio_wait_readable, 0);
+ kgio_wait_readable, -1);
rb_define_method(mWaiters, "kgio_wait_writable",
- kgio_wait_writable, 0);
+ kgio_wait_writable, -1);
}