Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# 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