make timed kgio_wait_* implementation safer
[kgio.git] / ext / kgio / wait.c
blobfe3896deb50c9589990ca8182e151936fc23b214
1 #include "kgio.h"
2 static ID id_wait_rd, id_wait_wr;
4 #if defined(HAVE_RB_TIME_INTERVAL) && defined(HAVE_RB_WAIT_FOR_SINGLE_FD)
5 static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
7 struct timeval tv = rb_time_interval(timeout);
8 int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;
10 return rb_wait_for_single_fd(my_fileno(self), events, &tv);
12 #else /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
13 static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
15 VALUE argv[4];
16 VALUE set = rb_ary_new3(1, self);
18 argv[0] = write_p ? Qnil : set;
19 argv[1] = write_p ? set : Qnil;
20 argv[2] = Qnil;
21 argv[3] = timeout;
23 set = rb_funcall2(rb_cIO, rb_intern("select"), 4, argv);
24 return NIL_P(set) ? 0 : 1;
26 #endif /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
28 static int kgio_wait(int argc, VALUE *argv, VALUE self, int write_p)
30 int fd;
31 VALUE timeout;
33 if (rb_scan_args(argc, argv, "01", &timeout) == 1 && !NIL_P(timeout))
34 return kgio_timedwait(self, timeout, write_p);
36 fd = my_fileno(self);
37 errno = EAGAIN;
38 write_p ? rb_io_wait_writable(fd) : rb_io_wait_readable(fd);
39 return 1;
43 * call-seq:
45 * io.kgio_wait_readable -> IO
46 * io.kgio_wait_readable(timeout) -> IO or nil
48 * Blocks the running Thread indefinitely until the IO object is readable
49 * or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
50 * is returned.
52 * This method is automatically called (without timeout argument) by default
53 * whenever kgio_read needs to block on input.
55 * Users of alternative threading/fiber libraries are
56 * encouraged to override this method in their subclasses or modules to
57 * work with their threading/blocking methods.
59 static VALUE kgio_wait_readable(int argc, VALUE *argv, VALUE self)
61 int r = kgio_wait(argc, argv, self, 0);
63 if (r < 0) rb_sys_fail("kgio_wait_readable");
64 return r == 0 ? Qnil : self;
68 * Blocks the running Thread indefinitely until the IO object is writable
69 * or if +timeout+ expires. If +timeout+ is specified and expires, +nil+
70 * is returned.
72 * This method is automatically called (without timeout argument) by default
73 * whenever kgio_write needs to block on output.
75 * Users of alternative threading/fiber libraries are
76 * encouraged to override this method in their subclasses or modules to
77 * work with their threading/blocking methods.
79 static VALUE kgio_wait_writable(int argc, VALUE *argv, VALUE self)
81 int r = kgio_wait(argc, argv, self, 1);
83 if (r < 0) rb_sys_fail("kgio_wait_writable");
84 return r == 0 ? Qnil : self;
87 VALUE kgio_call_wait_writable(VALUE io)
89 return rb_funcall(io, id_wait_wr, 0, 0);
92 VALUE kgio_call_wait_readable(VALUE io)
94 return rb_funcall(io, id_wait_rd, 0, 0);
97 void init_kgio_wait(void)
99 VALUE mKgio = rb_define_module("Kgio");
102 * Document-module: Kgio::DefaultWaiters
104 * This module contains default kgio_wait_readable and
105 * kgio_wait_writable methods that block indefinitely (in a
106 * thread-safe manner) until an IO object is read or writable.
107 * This module is included in the Kgio::PipeMethods and
108 * Kgio::SocketMethods modules used by all bundled IO-derived
109 * objects.
111 VALUE mWaiters = rb_define_module_under(mKgio, "DefaultWaiters");
113 id_wait_rd = rb_intern("kgio_wait_readable");
114 id_wait_wr = rb_intern("kgio_wait_writable");
116 rb_define_method(mWaiters, "kgio_wait_readable",
117 kgio_wait_readable, -1);
118 rb_define_method(mWaiters, "kgio_wait_writable",
119 kgio_wait_writable, -1);