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); }