Ruby
2.0.0p247(2013-06-27revision41674)
|
00001 /********************************************************************** 00002 00003 io/wait.c - 00004 00005 $Author: nobu $ 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 * 00100 * Waits until input is available or times out and returns self or nil when 00101 * EOF is reached. 00102 */ 00103 00104 static VALUE 00105 io_wait_readable(int argc, VALUE *argv, VALUE io) 00106 { 00107 rb_io_t *fptr; 00108 int i; 00109 ioctl_arg n; 00110 VALUE timeout; 00111 struct timeval timerec; 00112 struct timeval *tv; 00113 00114 GetOpenFile(io, fptr); 00115 rb_io_check_readable(fptr); 00116 rb_scan_args(argc, argv, "01", &timeout); 00117 if (NIL_P(timeout)) { 00118 tv = NULL; 00119 } 00120 else { 00121 timerec = rb_time_interval(timeout); 00122 tv = &timerec; 00123 } 00124 00125 if (rb_io_read_pending(fptr)) return Qtrue; 00126 if (!FIONREAD_POSSIBLE_P(fptr->fd)) return Qfalse; 00127 i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, tv); 00128 if (i < 0) 00129 rb_sys_fail(0); 00130 rb_io_check_closed(fptr); 00131 if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0); 00132 if (n > 0) return io; 00133 return Qnil; 00134 } 00135 00136 /* 00137 * call-seq: 00138 * io.wait_writable -> IO 00139 * io.wait_writable(timeout) -> IO or nil 00140 * 00141 * Waits until IO writable is available or times out and returns self or 00142 * nil when EOF is reached. 00143 */ 00144 static VALUE 00145 io_wait_writable(int argc, VALUE *argv, VALUE io) 00146 { 00147 rb_io_t *fptr; 00148 int i; 00149 VALUE timeout; 00150 struct timeval timerec; 00151 struct timeval *tv; 00152 00153 GetOpenFile(io, fptr); 00154 rb_io_check_writable(fptr); 00155 rb_scan_args(argc, argv, "01", &timeout); 00156 if (NIL_P(timeout)) { 00157 tv = NULL; 00158 } 00159 else { 00160 timerec = rb_time_interval(timeout); 00161 tv = &timerec; 00162 } 00163 00164 i = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_OUT, tv); 00165 if (i < 0) 00166 rb_sys_fail(0); 00167 rb_io_check_closed(fptr); 00168 if (i & RB_WAITFD_OUT) 00169 return io; 00170 return Qnil; 00171 } 00172 00173 /* 00174 * IO wait methods 00175 */ 00176 00177 void 00178 Init_wait() 00179 { 00180 rb_define_method(rb_cIO, "nread", io_nread, 0); 00181 rb_define_method(rb_cIO, "ready?", io_ready_p, 0); 00182 rb_define_method(rb_cIO, "wait", io_wait_readable, -1); 00183 rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1); 00184 rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1); 00185 } 00186