Ruby 1.9.3p327(2012-11-10revision37606)
ext/io/wait/wait.c
Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io/wait.c -
00004 
00005   $Author: kosaki $
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 /*
00044  * call-seq:
00045  *   io.nread -> int
00046  *
00047  * Returns number of bytes that can be read without blocking.
00048  * Returns zero if no information available.
00049  */
00050 
00051 static VALUE
00052 io_nread(VALUE io)
00053 {
00054     rb_io_t *fptr;
00055     int len;
00056     ioctl_arg n;
00057 
00058     GetOpenFile(io, fptr);
00059     rb_io_check_readable(fptr);
00060     len = rb_io_read_pending(fptr);
00061     if (len > 0) return len;
00062     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
00063     if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
00064     if (n > 0) return ioctl_arg2num(n);
00065     return INT2FIX(0);
00066 }
00067 
00068 /*
00069  * call-seq:
00070  *   io.ready? -> true, false or nil
00071  *
00072  * Returns true if input available without blocking, or false.
00073  * Returns nil if no information available.
00074  */
00075 
00076 static VALUE
00077 io_ready_p(VALUE io)
00078 {
00079     rb_io_t *fptr;
00080     ioctl_arg n;
00081 
00082     GetOpenFile(io, fptr);
00083     rb_io_check_readable(fptr);
00084     if (rb_io_read_pending(fptr)) return Qtrue;
00085     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qnil;
00086     if (ioctl(fptr->fd, FIONREAD, &n)) return Qnil;
00087     if (n > 0) return Qtrue;
00088     return Qfalse;
00089 }
00090 
00091 /*
00092  * call-seq:
00093  *   io.wait          -> IO, true, false or nil
00094  *   io.wait(timeout) -> IO, true, false or nil
00095  *
00096  * Waits until input is available or times out and returns self or nil when
00097  * EOF is reached.
00098  */
00099 
00100 static VALUE
00101 io_wait(int argc, VALUE *argv, VALUE io)
00102 {
00103     rb_io_t *fptr;
00104     int i;
00105     ioctl_arg n;
00106     VALUE timeout;
00107     struct timeval timerec;
00108     struct timeval *tv;
00109 
00110     GetOpenFile(io, fptr);
00111     rb_io_check_readable(fptr);
00112     rb_scan_args(argc, argv, "01", &timeout);
00113     if (NIL_P(timeout)) {
00114         tv = NULL;
00115     }
00116     else {
00117         timerec = rb_time_interval(timeout);
00118         tv = &timerec;
00119     }
00120 
00121     if (rb_io_read_pending(fptr)) return Qtrue;
00122     if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse;
00123     i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv);
00124     if (i < 0)
00125         rb_sys_fail(0);
00126     rb_io_check_closed(fptr);
00127     if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0);
00128     if (n > 0) return io;
00129     return Qnil;
00130 }
00131 
00132 /*
00133  * IO wait methods
00134  */
00135 
00136 void
00137 Init_wait()
00138 {
00139     rb_define_method(rb_cIO, "nread", io_nread, 0);
00140     rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
00141     rb_define_method(rb_cIO, "wait", io_wait, -1);
00142 }
00143