diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb index b5d36c3fe3..d20ff4553f 100644 --- a/ext/io/wait/extconf.rb +++ b/ext/io/wait/extconf.rb @@ -2,6 +2,7 @@ require 'mkmf' target = "io/wait" +have_func("rb_io_wait") unless macro_defined?("DOSISH", "#include ") have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h| diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c index 512e4f6a80..8f0d16e168 100644 --- a/ext/io/wait/wait.c +++ b/ext/io/wait/wait.c @@ -40,6 +40,37 @@ #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue) #endif +#ifndef HAVE_RB_IO_WAIT +static VALUE io_ready_p _((VALUE io)); +static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io)); +static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io)); +void Init_wait _((void)); + +static struct timeval * +get_timeout(int argc, VALUE *argv, struct timeval *timerec) +{ + VALUE timeout = Qnil; + rb_check_arity(argc, 0, 1); + if (!argc || NIL_P(timeout = argv[0])) { + return NULL; + } + else { + *timerec = rb_time_interval(timeout); + return timerec; + } +} + +static int +wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv) +{ + int i = rb_wait_for_single_fd(fptr->fd, events, tv); + if (i < 0) + rb_sys_fail(0); + rb_io_check_closed(fptr); + return (i & events); +} +#endif + /* * call-seq: * io.nread -> int @@ -51,12 +82,13 @@ static VALUE io_nread(VALUE io) { - rb_io_t *fptr = NULL; + rb_io_t *fptr; + int len; ioctl_arg n; GetOpenFile(io, fptr); rb_io_check_readable(fptr); - int len = rb_io_read_pending(fptr); + len = rb_io_read_pending(fptr); if (len > 0) return INT2FIX(len); if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0); if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0); @@ -64,6 +96,7 @@ io_nread(VALUE io) return INT2FIX(0); } +#ifdef HAVE_RB_IO_WAIT static VALUE io_wait_event(VALUE io, int event, VALUE timeout) { @@ -82,6 +115,7 @@ io_wait_event(VALUE io, int event, VALUE timeout) return Qfalse; } } +#endif /* * call-seq: @@ -94,12 +128,22 @@ static VALUE io_ready_p(VALUE io) { rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT + struct timeval tv = {0, 0}; +#endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; - return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0)); +#ifndef HAVE_RB_IO_WAIT + if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv)) + return Qtrue; +#else + if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0)))) + return Qtrue; +#endif + return Qfalse; } /* @@ -115,17 +159,31 @@ io_ready_p(VALUE io) static VALUE io_wait_readable(int argc, VALUE *argv, VALUE io) { - rb_io_t *fptr = NULL; + rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT + struct timeval timerec; + struct timeval *tv; +#endif - RB_IO_POINTER(io, fptr); + GetOpenFile(io, fptr); rb_io_check_readable(fptr); +#ifndef HAVE_RB_IO_WAIT + tv = get_timeout(argc, argv, &timerec); +#endif if (rb_io_read_pending(fptr)) return Qtrue; +#ifndef HAVE_RB_IO_WAIT + if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) { + return io; + } + return Qnil; +#else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_READABLE, timeout); +#endif } /* @@ -139,17 +197,30 @@ io_wait_readable(int argc, VALUE *argv, VALUE io) static VALUE io_wait_writable(int argc, VALUE *argv, VALUE io) { - rb_io_t *fptr = NULL; + rb_io_t *fptr; +#ifndef HAVE_RB_IO_WAIT + struct timeval timerec; + struct timeval *tv; +#endif - RB_IO_POINTER(io, fptr); + GetOpenFile(io, fptr); rb_io_check_writable(fptr); +#ifndef HAVE_RB_IO_WAIT + tv = get_timeout(argc, argv, &timerec); + if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) { + return io; + } + return Qnil; +#else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_WRITABLE, timeout); +#endif } +#ifdef HAVE_RB_IO_WAIT /* * call-seq: * io.wait_priority -> true or false @@ -173,6 +244,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io) return io_wait_event(io, RUBY_IO_PRIORITY, timeout); } +#endif static int wait_mode_sym(VALUE mode) @@ -228,6 +300,31 @@ wait_mode_sym(VALUE mode) static VALUE io_wait(int argc, VALUE *argv, VALUE io) { +#ifndef HAVE_RB_IO_WAIT + 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; +#else VALUE timeout = Qundef; rb_io_event_t events = 0; @@ -264,6 +361,7 @@ io_wait(int argc, VALUE *argv, VALUE io) } return io_wait_event(io, events, timeout); +#endif } /* @@ -284,5 +382,7 @@ Init_wait(void) rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1); rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1); +#ifdef HAVE_RB_IO_WAIT rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1); +#endif }