|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3