ext/kgio/wait.c in kgio-1.3.1 vs ext/kgio/wait.c in kgio-2.0.0pre1

- old
+ new

@@ -1,117 +1,81 @@ #include "kgio.h" -static ID io_wait_rd, io_wait_wr; +static ID id_wait_rd, id_wait_wr; -void kgio_wait_readable(VALUE io, int fd) -{ - if (io_wait_rd) { - (void)rb_funcall(io, io_wait_rd, 0, 0); - } else { - if (!rb_io_wait_readable(fd)) - rb_sys_fail("wait readable"); - } -} +/* + * 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... + */ -void kgio_wait_writable(VALUE io, int fd) -{ - if (io_wait_wr) { - (void)rb_funcall(io, io_wait_wr, 0, 0); - } else { - if (!rb_io_wait_writable(fd)) - rb_sys_fail("wait writable"); - } -} /* - * call-seq: + * Blocks the running Thread indefinitely until +self+ IO object is writable. + * This method is automatically called by default whenever kgio_read needs + * to block on input. * - * Kgio.wait_readable = :method_name - * Kgio.wait_readable = nil - * - * Sets a method for kgio_read to call when a read would block. - * This is useful for non-blocking frameworks that use Fibers, - * as the method referred to this may cause the current Fiber - * to yield execution. - * - * A special value of nil will cause Ruby to wait using the - * rb_io_wait_readable() function. + * 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 set_wait_rd(VALUE mod, VALUE sym) +static VALUE kgio_wait_readable(VALUE self) { - switch (TYPE(sym)) { - case T_SYMBOL: - io_wait_rd = SYM2ID(sym); - return sym; - case T_NIL: - io_wait_rd = 0; - return sym; - } - rb_raise(rb_eTypeError, "must be a symbol or nil"); - return sym; + errno = EAGAIN; + if (!rb_io_wait_readable(my_fileno(self))) + rb_sys_fail("kgio_wait_readable"); + + return self; } /* - * call-seq: - * - * Kgio.wait_writable = :method_name - * Kgio.wait_writable = nil - * - * Sets a method for kgio_write to call when a read would block. - * This is useful for non-blocking frameworks that use Fibers, - * as the method referred to this may cause the current Fiber - * to yield execution. - * - * A special value of nil will cause Ruby to wait using the - * rb_io_wait_writable() function. + * blocks the running Thread indefinitely until +self+ IO object is writable + * This method is automatically called 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 set_wait_wr(VALUE mod, VALUE sym) +static VALUE kgio_wait_writable(VALUE self) { - switch (TYPE(sym)) { - case T_SYMBOL: - io_wait_wr = SYM2ID(sym); - return sym; - case T_NIL: - io_wait_wr = 0; - return sym; - } - rb_raise(rb_eTypeError, "must be a symbol or nil"); - return sym; + errno = EAGAIN; + if (!rb_io_wait_writable(my_fileno(self))) + rb_sys_fail("kgio_wait_writable"); + + return self; } -/* - * call-seq: - * - * Kgio.wait_writable -> Symbol or nil - * - * Returns the symbolic method name of the method assigned to - * call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_write - * or Kgio::SocketMethods#kgio_write call - */ -static VALUE wait_wr(VALUE mod) +VALUE kgio_call_wait_writable(VALUE io) { - return io_wait_wr ? ID2SYM(io_wait_wr) : Qnil; + return rb_funcall(io, id_wait_wr, 0, 0); } -/* - * call-seq: - * - * Kgio.wait_readable -> Symbol or nil - * - * Returns the symbolic method name of the method assigned to - * call when EAGAIN is occurs on a Kgio::PipeMethods#kgio_read - * or Kgio::SocketMethods#kgio_read call. - */ -static VALUE wait_rd(VALUE mod) +VALUE kgio_call_wait_readable(VALUE io) { - return io_wait_rd ? ID2SYM(io_wait_rd) : Qnil; + return rb_funcall(io, id_wait_rd, 0, 0); } void init_kgio_wait(void) { VALUE mKgio = rb_define_module("Kgio"); - rb_define_singleton_method(mKgio, "wait_readable=", set_wait_rd, 1); - rb_define_singleton_method(mKgio, "wait_writable=", set_wait_wr, 1); - rb_define_singleton_method(mKgio, "wait_readable", wait_rd, 0); - rb_define_singleton_method(mKgio, "wait_writable", wait_wr, 0); + /* + * Document-module: Kgio::DefaultWaiters + * + * This module contains default kgio_wait_readable and + * kgio_wait_writable methods that block indefinitely (in a + * thread-safe manner) until an IO object is read or writable. + * This module is included in the Kgio::PipeMethods and + * Kgio::SocketMethods modules used by all bundled IO-derived + * objects. + */ + VALUE mWaiters = rb_define_module_under(mKgio, "DefaultWaiters"); + + 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); + rb_define_method(mWaiters, "kgio_wait_writable", + kgio_wait_writable, 0); }