ext/io/wait/wait.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io/wait.c -
00004 
00005   $Author: zzak $
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_UNISTD_H) && (defined(__sun))
00018 #include <unistd.h>
00019 #endif
00020 #if defined(HAVE_SYS_IOCTL_H)
00021 #include <sys/ioctl.h>
00022 #endif
00023 #if defined(FIONREAD_HEADER)
00024 #include FIONREAD_HEADER
00025 #endif
00026 
00027 #ifdef HAVE_RB_W32_IOCTLSOCKET
00028 #define ioctl ioctlsocket
00029 #define ioctl_arg u_long
00030 #define ioctl_arg2num(i) ULONG2NUM(i)
00031 #else
00032 #define ioctl_arg int
00033 #define ioctl_arg2num(i) INT2NUM(i)
00034 #endif
00035 
00036 #ifdef HAVE_RB_W32_IS_SOCKET
00037 #define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
00038 #else
00039 #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
00040 #endif
00041 
00042 static VALUE io_ready_p _((VALUE io));
00043 static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
00044 static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
00045 void Init_wait _((void));
00046 
00047 /*
00048  * call-seq:
00049  *   io.nread -> int
00050  *
00051  * Returns number of bytes that can be read without blocking.
00052  * Returns zero if no information available.
00053  */
00054 
00055 static VALUE
00056 io_nread(VALUE io)
00057 {
00058     rb_io_t *fptr;
00059     int len;
00060     ioctl_arg n;
00061 
00062     GetOpenFile(io, fptr);
00063     rb_io_check_readable(fptr);
00064     len = rb_io_read_pending(fptr);
00065     if (len > 0) return len;
00066     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
00067     if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
00068     if (n > 0) return ioctl_arg2num(n);
00069     return INT2FIX(0);
00070 }
00071 
00072 /*
00073  * call-seq:
00074  *   io.ready? -> true, false or nil
00075  *
00076  * Returns true if input available without blocking, or false.
00077  * Returns nil if no information available.
00078  */
00079 
00080 static VALUE
00081 io_ready_p(VALUE io)
00082 {
00083     rb_io_t *fptr;
00084     ioctl_arg n;
00085 
00086     GetOpenFile(io, fptr);
00087     rb_io_check_readable(fptr);
00088     if (rb_io_read_pending(fptr)) return Qtrue;
00089     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qnil;
00090     if (ioctl(fptr->fd, FIONREAD, &n)) return Qnil;
00091     if (n > 0) return Qtrue;
00092     return Qfalse;
00093 }
00094 
00095 /*
00096  * call-seq:
00097  *   io.wait          -> IO, true, false or nil
00098  *   io.wait(timeout) -> IO, true, false or nil
00099  *   io.wait_readable          -> IO, true, false or nil
00100  *   io.wait_readable(timeout) -> IO, true, false or nil
00101  *
00102  * Waits until input is available or times out and returns self or nil when
00103  * EOF is reached.
00104  */
00105 
00106 static VALUE
00107 io_wait_readable(int argc, VALUE *argv, VALUE io)
00108 {
00109     rb_io_t *fptr;
00110     int i;
00111     ioctl_arg n;
00112     VALUE timeout;
00113     struct timeval timerec;
00114     struct timeval *tv;
00115 
00116     GetOpenFile(io, fptr);
00117     rb_io_check_readable(fptr);
00118     rb_scan_args(argc, argv, "01", &timeout);
00119     if (NIL_P(timeout)) {
00120         tv = NULL;
00121     }
00122     else {
00123         timerec = rb_time_interval(timeout);
00124         tv = &timerec;
00125     }
00126 
00127     if (rb_io_read_pending(fptr)) return Qtrue;
00128     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
00129     i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv);
00130     if (i < 0)
00131         rb_sys_fail(0);
00132     rb_io_check_closed(fptr);
00133     if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
00134     if (n > 0) return io;
00135     return Qnil;
00136 }
00137 
00138 /*
00139  * call-seq:
00140  *   io.wait_writable          -> IO
00141  *   io.wait_writable(timeout) -> IO or nil
00142  *
00143  * Waits until IO writable is available or times out and returns self or
00144  * nil when EOF is reached.
00145  */
00146 static VALUE
00147 io_wait_writable(int argc, VALUE *argv, VALUE io)
00148 {
00149     rb_io_t *fptr;
00150     int i;
00151     VALUE timeout;
00152     struct timeval timerec;
00153     struct timeval *tv;
00154 
00155     GetOpenFile(io, fptr);
00156     rb_io_check_writable(fptr);
00157     rb_scan_args(argc, argv, "01", &timeout);
00158     if (NIL_P(timeout)) {
00159         tv = NULL;
00160     }
00161     else {
00162         timerec = rb_time_interval(timeout);
00163         tv = &timerec;
00164     }
00165 
00166     i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_OUT, tv);
00167     if (i < 0)
00168         rb_sys_fail(0);
00169     rb_io_check_closed(fptr);
00170     if (i & RB_WAITFD_OUT)
00171         return io;
00172     return Qnil;
00173 }
00174 
00175 /*
00176  * IO wait methods
00177  */
00178 
00179 void
00180 Init_wait()
00181 {
00182     rb_define_method(rb_cIO, "nread", io_nread, 0);
00183     rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
00184     rb_define_method(rb_cIO, "wait", io_wait_readable, -1);
00185     rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
00186     rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
00187 }
00188 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7