2 #if defined(USE_KGIO_POLL)
4 #include "broken_system_compat.h"
13 static VALUE sym_wait_readable
, sym_wait_writable
;
22 struct timespec start
;
25 static int interrupted(void)
37 static int retryable(struct poll_args
*a
)
46 clock_gettime(hopefully_CLOCK_MONOTONIC
, &ts
);
48 ts
.tv_sec
-= a
->start
.tv_sec
;
49 ts
.tv_nsec
-= a
->start
.tv_nsec
;
52 ts
.tv_nsec
+= 1000000000;
54 a
->timeout
-= ts
.tv_sec
* 1000;
55 a
->timeout
-= ts
.tv_nsec
/ 1000000;
56 return (a
->timeout
>= 0);
59 static int num2timeout(VALUE timeout
)
61 switch (TYPE(timeout
)) {
62 case T_NIL
: return -1;
63 case T_FIXNUM
: return FIX2INT(timeout
);
64 case T_BIGNUM
: return NUM2INT(timeout
);
66 rb_raise(rb_eTypeError
, "timeout must be integer or nil");
70 static VALUE
poll_free(VALUE args
)
72 struct poll_args
*a
= (struct poll_args
*)args
;
77 st_free_table(a
->fd_to_io
);
82 static short value2events(VALUE event
)
84 if (event
== sym_wait_readable
) return POLLIN
;
85 if (event
== sym_wait_writable
) return POLLOUT
;
86 if (TYPE(event
) == T_FIXNUM
) return (short)FIX2INT(event
);
87 rb_raise(rb_eArgError
, "unrecognized event");
90 static int io_to_pollfd_i(VALUE key
, VALUE value
, VALUE args
)
92 struct poll_args
*a
= (struct poll_args
*)args
;
93 struct pollfd
*pollfd
= &a
->fds
[a
->nfds
++];
95 pollfd
->fd
= my_fileno(key
);
96 pollfd
->events
= value2events(value
);
97 st_insert(a
->fd_to_io
, (st_data_t
)pollfd
->fd
, (st_data_t
)key
);
101 static void hash2pollfds(struct poll_args
*a
)
104 a
->fds
= xmalloc(sizeof(struct pollfd
) * RHASH_SIZE(a
->ios
));
105 a
->fd_to_io
= st_init_numtable();
106 rb_hash_foreach(a
->ios
, io_to_pollfd_i
, (VALUE
)a
);
109 static VALUE
nogvl_poll(void *ptr
)
111 struct poll_args
*a
= ptr
;
114 clock_gettime(hopefully_CLOCK_MONOTONIC
, &a
->start
);
116 return (VALUE
)poll(a
->fds
, a
->nfds
, a
->timeout
);
119 static VALUE
poll_result(int nr
, struct poll_args
*a
)
121 struct pollfd
*fds
= a
->fds
;
125 if ((nfds_t
)nr
!= a
->nfds
)
126 rb_funcall(a
->ios
, id_clear
, 0);
127 for (; nr
> 0; fds
++) {
128 if (fds
->revents
== 0)
131 rc
= st_lookup(a
->fd_to_io
, (st_data_t
)fds
->fd
, &io
);
132 assert(rc
== 1 && "fd => IO mapping failed");
133 rb_hash_aset(a
->ios
, io
, INT2FIX((int)fds
->revents
));
138 static VALUE
do_poll(VALUE args
)
140 struct poll_args
*a
= (struct poll_args
*)args
;
143 Check_Type(a
->ios
, T_HASH
);
147 nr
= (int)rb_thread_blocking_region(nogvl_poll
, a
, RUBY_UBF_IO
, NULL
);
158 if (nr
== 0) return Qnil
;
160 return poll_result(nr
, a
);
166 * Kgio.poll({ $stdin => :wait_readable }, 100) -> hash or nil
167 * Kgio.poll({ $stdin => Kgio::POLLIN }, 100) -> hash or nil
169 * Accepts an input hash with IO objects to wait for as the key and
170 * the events to wait for as its value. The events may either be
171 * +:wait_readable+ or +:wait_writable+ symbols or a Fixnum mask of
172 * Kgio::POLL* constants:
174 * Kgio::POLLIN - there is data to read
175 * Kgio::POLLPRI - there is urgent data to read
176 * Kgio::POLLOUT - writing will not block
177 * Kgio::POLLRDHUP - peer has shutdown writes (Linux 2.6.17+ only)
179 * Timeout is specified in Integer milliseconds just like the underlying
180 * poll(2), not in seconds like IO.select. A nil timeout means to wait
181 * forever. It must be an Integer or nil.
183 * Kgio.poll modifies and returns its input hash on success with the
184 * IO-like object as the key and an Integer mask of events as the hash
185 * value. It can return any of the events specified in the input
186 * above, along with the following events:
188 * Kgio::POLLERR - error condition occurred on the descriptor
189 * Kgio::POLLHUP - hang up
190 * Kgio::POLLNVAL - invalid request (bad file descriptor)
192 * This method is only available under Ruby 1.9 or any other
193 * implementations that uses native threads and rb_thread_blocking_region()
195 static VALUE
s_poll(int argc
, VALUE
*argv
, VALUE self
)
200 rb_scan_args(argc
, argv
, "11", &a
.ios
, &timeout
);
201 a
.timeout
= num2timeout(timeout
);
205 return rb_ensure(do_poll
, (VALUE
)&a
, poll_free
, (VALUE
)&a
);
208 void init_kgio_poll(void)
210 VALUE mKgio
= rb_define_module("Kgio");
212 if (check_clock() < 0)
214 rb_define_singleton_method(mKgio
, "poll", s_poll
, -1);
216 sym_wait_readable
= ID2SYM(rb_intern("wait_readable"));
217 sym_wait_writable
= ID2SYM(rb_intern("wait_writable"));
218 id_clear
= rb_intern("clear");
220 #define c(x) rb_define_const(mKgio,#x,INT2NUM((int)x))
237 #else /* ! USE_KGIO_POLL */
238 void init_kgio_poll(void)
241 #endif /* ! USE_KGIO_POLL */