1414#include "ruby.h"
1515#include "ruby/io.h"
1616
17- #ifndef RUBY_IO_WAIT_METHODS
18- /* Ruby 3.2+ can define these methods. This macro indicates that case. */
19-
20- static VALUE
21- io_wait_event (VALUE io , int event , VALUE timeout , int return_io )
22- {
23- VALUE result = rb_io_wait (io , RB_INT2NUM (event ), timeout );
24-
25- if (!RB_TEST (result )) {
26- return Qnil ;
27- }
28-
29- int mask = RB_NUM2INT (result );
30-
31- if (mask & event ) {
32- if (return_io )
33- return io ;
34- else
35- return result ;
36- }
37- else {
38- return Qfalse ;
39- }
40- }
41-
42- /*
43- * call-seq:
44- * io.wait_readable -> truthy or falsy
45- * io.wait_readable(timeout) -> truthy or falsy
46- *
47- * Waits until IO is readable and returns a truthy value, or a falsy
48- * value when times out. Returns a truthy value immediately when
49- * buffered data is available.
50- *
51- * You must require 'io/wait' to use this method.
52- */
53-
54- static VALUE
55- io_wait_readable (int argc , VALUE * argv , VALUE io )
56- {
57- rb_io_t * fptr ;
58-
59- GetOpenFile (io , fptr );
60- rb_io_check_char_readable (fptr );
61-
62- if (rb_io_read_pending (fptr )) return Qtrue ;
63-
64- rb_check_arity (argc , 0 , 1 );
65- VALUE timeout = (argc == 1 ? argv [0 ] : Qnil );
66-
67- return io_wait_event (io , RUBY_IO_READABLE , timeout , 1 );
68- }
69-
70- /*
71- * call-seq:
72- * io.wait_writable -> truthy or falsy
73- * io.wait_writable(timeout) -> truthy or falsy
74- *
75- * Waits until IO is writable and returns a truthy value or a falsy
76- * value when times out.
77- *
78- * You must require 'io/wait' to use this method.
79- */
80- static VALUE
81- io_wait_writable (int argc , VALUE * argv , VALUE io )
82- {
83- rb_io_t * fptr ;
84-
85- GetOpenFile (io , fptr );
86- rb_io_check_writable (fptr );
87-
88- rb_check_arity (argc , 0 , 1 );
89- VALUE timeout = (argc == 1 ? argv [0 ] : Qnil );
90-
91- return io_wait_event (io , RUBY_IO_WRITABLE , timeout , 1 );
92- }
93-
94- /*
95- * call-seq:
96- * io.wait_priority -> truthy or falsy
97- * io.wait_priority(timeout) -> truthy or falsy
98- *
99- * Waits until IO is priority and returns a truthy value or a falsy
100- * value when times out. Priority data is sent and received using
101- * the Socket::MSG_OOB flag and is typically limited to streams.
102- *
103- * You must require 'io/wait' to use this method.
104- */
105- static VALUE
106- io_wait_priority (int argc , VALUE * argv , VALUE io )
107- {
108- rb_io_t * fptr = NULL ;
109-
110- RB_IO_POINTER (io , fptr );
111- rb_io_check_char_readable (fptr );
112-
113- if (rb_io_read_pending (fptr )) return Qtrue ;
114-
115- rb_check_arity (argc , 0 , 1 );
116- VALUE timeout = argc == 1 ? argv [0 ] : Qnil ;
117-
118- return io_wait_event (io , RUBY_IO_PRIORITY , timeout , 1 );
119- }
120-
121- static int
122- wait_mode_sym (VALUE mode )
123- {
124- if (mode == ID2SYM (rb_intern ("r" ))) {
125- return RB_WAITFD_IN ;
126- }
127- if (mode == ID2SYM (rb_intern ("read" ))) {
128- return RB_WAITFD_IN ;
129- }
130- if (mode == ID2SYM (rb_intern ("readable" ))) {
131- return RB_WAITFD_IN ;
132- }
133- if (mode == ID2SYM (rb_intern ("w" ))) {
134- return RB_WAITFD_OUT ;
135- }
136- if (mode == ID2SYM (rb_intern ("write" ))) {
137- return RB_WAITFD_OUT ;
138- }
139- if (mode == ID2SYM (rb_intern ("writable" ))) {
140- return RB_WAITFD_OUT ;
141- }
142- if (mode == ID2SYM (rb_intern ("rw" ))) {
143- return RB_WAITFD_IN |RB_WAITFD_OUT ;
144- }
145- if (mode == ID2SYM (rb_intern ("read_write" ))) {
146- return RB_WAITFD_IN |RB_WAITFD_OUT ;
147- }
148- if (mode == ID2SYM (rb_intern ("readable_writable" ))) {
149- return RB_WAITFD_IN |RB_WAITFD_OUT ;
150- }
151- rb_raise (rb_eArgError , "unsupported mode: %" PRIsVALUE , mode );
152- return 0 ;
153- }
154-
155- static inline rb_io_event_t
156- io_event_from_value (VALUE value )
157- {
158- int events = RB_NUM2INT (value );
159-
160- if (events <= 0 ) rb_raise (rb_eArgError , "Events must be positive integer!" );
161-
162- return events ;
163- }
164-
165- /*
166- * call-seq:
167- * io.wait(events, timeout) -> event mask, false or nil
168- * io.wait(*event_symbols[, timeout]) -> self, true, or false
169- *
170- * Waits until the IO becomes ready for the specified events and returns the
171- * subset of events that become ready, or a falsy value when times out.
172- *
173- * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
174- * +IO::PRIORITY+.
175- *
176- * Returns an event mask (truthy value) immediately when buffered data is
177- * available.
178- *
179- * The second form: if one or more event symbols (+:read+, +:write+, or
180- * +:read_write+) are passed, the event mask is the bit OR of the bitmask
181- * corresponding to those symbols. In this form, +timeout+ is optional, the
182- * order of the arguments is arbitrary, and returns +io+ if any of the
183- * events is ready.
184- *
185- * You must require 'io/wait' to use this method.
186- */
187-
188- static VALUE
189- io_wait (int argc , VALUE * argv , VALUE io )
190- {
191- VALUE timeout = Qundef ;
192- rb_io_event_t events = 0 ;
193- int i , return_io = 0 ;
194-
195- if (argc != 2 || (RB_SYMBOL_P (argv [0 ]) || RB_SYMBOL_P (argv [1 ]))) {
196- /* We'd prefer to return the actual mask, but this form would return the io itself: */
197- return_io = 1 ;
198-
199- /* Slow/messy path: */
200- for (i = 0 ; i < argc ; i += 1 ) {
201- if (RB_SYMBOL_P (argv [i ])) {
202- events |= wait_mode_sym (argv [i ]);
203- }
204- else if (timeout == Qundef ) {
205- rb_time_interval (timeout = argv [i ]);
206- }
207- else {
208- rb_raise (rb_eArgError , "timeout given more than once" );
209- }
210- }
211-
212- if (timeout == Qundef ) timeout = Qnil ;
213-
214- if (events == 0 ) {
215- events = RUBY_IO_READABLE ;
216- }
217- }
218- else /* argc == 2 and neither are symbols */ {
219- /* This is the fast path: */
220- events = io_event_from_value (argv [0 ]);
221- timeout = argv [1 ];
222- }
223-
224- if (events & RUBY_IO_READABLE ) {
225- rb_io_t * fptr = NULL ;
226- RB_IO_POINTER (io , fptr );
227-
228- if (rb_io_read_pending (fptr )) {
229- /* This was the original behaviour: */
230- if (return_io ) return Qtrue ;
231- /* New behaviour always returns an event mask: */
232- else return RB_INT2NUM (RUBY_IO_READABLE );
233- }
234- }
235-
236- return io_wait_event (io , events , timeout , return_io );
237- }
238-
239- #endif /* RUBY_IO_WAIT_METHODS */
24017
24118/*
24219 * IO wait methods
@@ -249,11 +26,4 @@ Init_wait(void)
24926 RB_EXT_RACTOR_SAFE (true);
25027#endif
25128
252- #ifndef RUBY_IO_WAIT_METHODS
253- rb_define_method (rb_cIO , "wait" , io_wait , -1 );
254-
255- rb_define_method (rb_cIO , "wait_readable" , io_wait_readable , -1 );
256- rb_define_method (rb_cIO , "wait_writable" , io_wait_writable , -1 );
257- rb_define_method (rb_cIO , "wait_priority" , io_wait_priority , -1 );
258- #endif
25929}
0 commit comments