2 #if defined(HAVE_RB_THREAD_BLOCKING_REGION) && defined(HAVE_POLL)
10 static VALUE sym_wait_readable
, sym_wait_writable
;
21 static int num2timeout(VALUE timeout
)
23 switch (TYPE(timeout
)) {
24 case T_NIL
: return -1;
25 case T_FIXNUM
: return FIX2INT(timeout
);
26 case T_BIGNUM
: return NUM2INT(timeout
);
28 rb_raise(rb_eTypeError
, "timeout must be integer or nil");
32 static VALUE
poll_free(VALUE args
)
34 struct poll_args
*a
= (struct poll_args
*)args
;
39 st_free_table(a
->fd_to_io
);
44 static short value2events(VALUE event
)
46 if (event
== sym_wait_readable
) return POLLIN
;
47 if (event
== sym_wait_writable
) return POLLOUT
;
48 if (TYPE(event
) == T_FIXNUM
) return (short)FIX2INT(event
);
49 rb_raise(rb_eArgError
, "unrecognized event");
52 static int io_to_pollfd_i(VALUE key
, VALUE value
, VALUE args
)
54 struct poll_args
*a
= (struct poll_args
*)args
;
55 struct pollfd
*pollfd
= &a
->fds
[a
->nfds
++];
57 pollfd
->fd
= my_fileno(key
);
58 pollfd
->events
= value2events(value
);
59 st_insert(a
->fd_to_io
, (st_data_t
)pollfd
->fd
, (st_data_t
)key
);
63 static void hash2pollfds(struct poll_args
*a
)
65 a
->fds
= xmalloc(sizeof(struct poll_args
) * RHASH_SIZE(a
->ios
));
66 a
->fd_to_io
= st_init_numtable();
67 rb_hash_foreach(a
->ios
, io_to_pollfd_i
, (VALUE
)a
);
70 static VALUE
nogvl_poll(void *ptr
)
72 struct poll_args
*a
= ptr
;
73 return (VALUE
)poll(a
->fds
, a
->nfds
, a
->timeout
);
76 static VALUE
poll_result(int nr
, struct poll_args
*a
)
78 struct pollfd
*fds
= a
->fds
;
82 if ((nfds_t
)nr
!= a
->nfds
)
83 rb_funcall(a
->ios
, id_clear
, 0);
84 for (; nr
> 0; fds
++) {
85 if (fds
->revents
== 0)
88 rc
= st_lookup(a
->fd_to_io
, (st_data_t
)fds
->fd
, &io
);
89 assert(rc
== 1 && "fd => IO mapping failed");
90 rb_hash_aset(a
->ios
, io
, INT2FIX((int)fds
->revents
));
95 static VALUE
do_poll(VALUE args
)
97 struct poll_args
*a
= (struct poll_args
*)args
;
100 Check_Type(a
->ios
, T_HASH
);
103 nr
= (int)rb_thread_blocking_region(nogvl_poll
, a
, RUBY_UBF_IO
, NULL
);
104 if (nr
< 0) rb_sys_fail("poll");
105 if (nr
== 0) return Qnil
;
107 return poll_result(nr
, a
);
113 * Kgio.poll({ $stdin => :wait_readable }, 100) -> hash or nil
114 * Kgio.poll({ $stdin => Kgio::POLLIN }, 100) -> hash or nil
116 * Accepts an input hash with IO objects to wait for as the key and
117 * the events to wait for as its value. The events may either be
118 * +:wait_readable+ or +:wait_writable+ symbols or a Fixnum mask of
119 * Kgio::POLL* constants:
121 * Kgio::POLLIN - there is data to read
122 * Kgio::POLLPRI - there is urgent data to read
123 * Kgio::POLLOUT - writing will not block
124 * Kgio::POLLRDHUP - peer has shutdown writes (Linux 2.6.17+ only)
126 * Timeout is specified in Integer milliseconds just like the underlying
127 * poll(2), not in seconds like IO.select. A nil timeout means to wait
128 * forever. It must be an Integer or nil.
130 * Kgio.poll modifies and returns its input hash on success with the
131 * IO-like object as the key and an Integer mask of events as the hash
132 * value. It can return any of the events specified in the input
133 * above, along with the following events:
135 * Kgio::POLLERR - error condition occurred on the descriptor
136 * Kgio::POLLHUP - hang up
137 * Kgio::POLLNVAL - invalid request (bad file descriptor)
139 * This method is only available under Ruby 1.9 or any other
140 * implementations that uses native threads and rb_thread_blocking_region()
142 static VALUE
s_poll(int argc
, VALUE
*argv
, VALUE self
)
147 rb_scan_args(argc
, argv
, "11", &a
.ios
, &timeout
);
148 a
.timeout
= num2timeout(timeout
);
153 return rb_ensure(do_poll
, (VALUE
)&a
, poll_free
, (VALUE
)&a
);
156 void init_kgio_poll(void)
158 VALUE mKgio
= rb_define_module("Kgio");
159 rb_define_singleton_method(mKgio
, "poll", s_poll
, -1);
161 sym_wait_readable
= ID2SYM(rb_intern("wait_readable"));
162 sym_wait_writable
= ID2SYM(rb_intern("wait_writable"));
163 id_clear
= rb_intern("clear");
165 #define c(x) rb_define_const(mKgio,#x,INT2NUM((int)x))
182 #else /* ! HAVE_RB_THREAD_BLOCKING_REGION */
183 void init_kgio_poll(void)
186 #endif /* ! HAVE_RB_THREAD_BLOCKIONG_REGION */