00001
00002 #include "ruby/ruby.h"
00003 #include "ruby/io.h"
00004
00005 static fd_set * array2fdset(fd_set *fds, VALUE ary, int *max)
00006 {
00007 long i;
00008
00009 if (NIL_P(ary))
00010 return NULL;
00011
00012 FD_ZERO(fds);
00013 Check_Type(ary, T_ARRAY);
00014 for (i = 0; i < RARRAY_LEN(ary); i++) {
00015 VALUE val = RARRAY_PTR(ary)[i];
00016 int fd;
00017
00018 Check_Type(val, T_FIXNUM);
00019 fd = FIX2INT(val);
00020 if (fd >= *max)
00021 *max = fd + 1;
00022 FD_SET(fd, fds);
00023 }
00024
00025 return fds;
00026 }
00027
00028 static void fdset2array(VALUE dst, fd_set *fds, int max)
00029 {
00030 int i;
00031
00032 rb_ary_clear(dst);
00033
00034 for (i = 0; i < max; i++) {
00035 if (FD_ISSET(i, fds))
00036 rb_ary_push(dst, INT2NUM(i));
00037 }
00038 }
00039
00040 static VALUE
00041 old_thread_select(VALUE klass, VALUE r, VALUE w, VALUE e, VALUE timeout)
00042 {
00043 struct timeval tv;
00044 struct timeval *tvp = NULL;
00045 fd_set rfds, wfds, efds;
00046 fd_set *rp, *wp, *ep;
00047 int rc;
00048 int max = 0;
00049
00050 if (!NIL_P(timeout)) {
00051 tv = rb_time_timeval(timeout);
00052 tvp = &tv;
00053 }
00054 rp = array2fdset(&rfds, r, &max);
00055 wp = array2fdset(&wfds, w, &max);
00056 ep = array2fdset(&efds, e, &max);
00057 rc = rb_thread_select(max, rp, wp, ep, tvp);
00058 if (rc == -1)
00059 rb_sys_fail("rb_wait_for_single_fd");
00060
00061 if (rp)
00062 fdset2array(r, &rfds, max);
00063 if (wp)
00064 fdset2array(w, &wfds, max);
00065 if (ep)
00066 fdset2array(e, &efds, max);
00067 return INT2NUM(rc);
00068 }
00069
00070 void
00071 Init_old_thread_select(void)
00072 {
00073 rb_define_singleton_method(rb_cIO, "old_thread_select",
00074 old_thread_select, 4);
00075 }
00076