ext/io/wait/wait.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io/wait.c -
00004 
00005   $Author: akr $
00006   created at: Tue Aug 28 09:08:06 JST 2001
00007 
00008   All the files in this distribution are covered under the Ruby's
00009   license (see the file COPYING).
00010 
00011 **********************************************************************/
00012 
00013 #include "ruby.h"
00014 #include "ruby/io.h"
00015 
00016 #include <sys/types.h>
00017 #if defined(HAVE_SYS_IOCTL_H)
00018 #include <sys/ioctl.h>
00019 #endif
00020 #if defined(FIONREAD_HEADER)
00021 #include FIONREAD_HEADER
00022 #endif
00023 
00024 #ifdef HAVE_RB_W32_IOCTLSOCKET
00025 #define ioctl ioctlsocket
00026 #define ioctl_arg u_long
00027 #define ioctl_arg2num(i) ULONG2NUM(i)
00028 #else
00029 #define ioctl_arg int
00030 #define ioctl_arg2num(i) INT2NUM(i)
00031 #endif
00032 
00033 #ifdef HAVE_RB_W32_IS_SOCKET
00034 #define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
00035 #else
00036 #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
00037 #endif
00038 
00039 static VALUE io_ready_p _((VALUE io));
00040 static VALUE io_wait _((int argc, VALUE *argv, VALUE io));
00041 void Init_wait _((void));
00042 
00043 EXTERN struct timeval rb_time_interval _((VALUE time));
00044 
00045 /*
00046  * call-seq:
00047  *   io.nread -> int
00048  *
00049  * Returns number of bytes that can be read without blocking.
00050  * Returns zero if no information available.
00051  */
00052 
00053 static VALUE
00054 io_nread(VALUE io)
00055 {
00056     rb_io_t *fptr;
00057     int len;
00058     ioctl_arg n;
00059 
00060     GetOpenFile(io, fptr);
00061     rb_io_check_readable(fptr);
00062     len = rb_io_read_pending(fptr);
00063     if (len > 0) return len;
00064     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
00065     if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
00066     if (n > 0) return ioctl_arg2num(n);
00067     return INT2FIX(0);
00068 }
00069 
00070 /*
00071  * call-seq:
00072  *   io.ready? -> true, false or nil
00073  *
00074  * Returns true if input available without blocking, or false.
00075  * Returns nil if no information available.
00076  */
00077 
00078 static VALUE
00079 io_ready_p(VALUE io)
00080 {
00081     rb_io_t *fptr;
00082     ioctl_arg n;
00083 
00084     GetOpenFile(io, fptr);
00085     rb_io_check_readable(fptr);
00086     if (rb_io_read_pending(fptr)) return Qtrue;
00087     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qnil;
00088     if (ioctl(fptr->fd, FIONREAD, &n)) return Qnil;
00089     if (n > 0) return Qtrue;
00090     return Qfalse;
00091 }
00092 
00093 struct wait_readable_arg {
00094     rb_fdset_t fds;
00095     struct timeval *timeout;
00096 };
00097 
00098 #ifdef HAVE_RB_FD_INIT
00099 static VALUE
00100 wait_readable(VALUE p)
00101 {
00102     struct wait_readable_arg *arg = (struct wait_readable_arg *)p;
00103     rb_fdset_t *fds = &arg->fds;
00104 
00105     return (VALUE)rb_thread_select(rb_fd_max(fds), rb_fd_ptr(fds), NULL, NULL, arg->timeout);
00106 }
00107 #endif
00108 
00109 /*
00110  * call-seq:
00111  *   io.wait          -> IO, true, false or nil
00112  *   io.wait(timeout) -> IO, true, false or nil
00113  *
00114  * Waits until input is available or times out and returns self or nil when
00115  * EOF is reached.
00116  */
00117 
00118 static VALUE
00119 io_wait(int argc, VALUE *argv, VALUE io)
00120 {
00121     rb_io_t *fptr;
00122     struct wait_readable_arg arg;
00123     int fd, i;
00124     ioctl_arg n;
00125     VALUE timeout;
00126     struct timeval timerec;
00127 
00128     GetOpenFile(io, fptr);
00129     rb_io_check_readable(fptr);
00130     rb_scan_args(argc, argv, "01", &timeout);
00131     if (NIL_P(timeout)) {
00132         arg.timeout = 0;
00133     }
00134     else {
00135         timerec = rb_time_interval(timeout);
00136         arg.timeout = &timerec;
00137     }
00138 
00139     if (rb_io_read_pending(fptr)) return Qtrue;
00140     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
00141     fd = fptr->fd;
00142     rb_fd_init(&arg.fds);
00143     rb_fd_set(fd, &arg.fds);
00144 #ifdef HAVE_RB_FD_INIT
00145     i = (int)rb_ensure(wait_readable, (VALUE)&arg,
00146                        (VALUE (*)_((VALUE)))rb_fd_term, (VALUE)&arg.fds);
00147 #else
00148     i = rb_thread_select(fd + 1, rb_fd_ptr(&arg.fds), NULL, NULL, arg.timeout);
00149 #endif
00150     if (i < 0)
00151         rb_sys_fail(0);
00152     rb_io_check_closed(fptr);
00153     if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
00154     if (n > 0) return io;
00155     return Qnil;
00156 }
00157 
00158 /*
00159  * IO wait methods
00160  */
00161 
00162 void
00163 Init_wait()
00164 {
00165     rb_define_method(rb_cIO, "nread", io_nread, 0);
00166     rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
00167     rb_define_method(rb_cIO, "wait", io_wait, -1);
00168 }
00169 

Generated on Wed Aug 10 09:17:00 2011 for Ruby by  doxygen 1.4.7