@@ -95,21 +95,24 @@ io_nread(VALUE io)
95
95
96
96
#ifdef HAVE_RB_IO_WAIT
97
97
static VALUE
98
- io_wait_event (VALUE io , int event , VALUE timeout )
98
+ io_wait_event (VALUE io , int event , VALUE timeout , int return_io )
99
99
{
100
100
VALUE result = rb_io_wait (io , RB_INT2NUM (event ), timeout );
101
101
102
102
if (!RB_TEST (result )) {
103
- return Qnil ;
103
+ return Qnil ;
104
104
}
105
105
106
106
int mask = RB_NUM2INT (result );
107
107
108
108
if (mask & event ) {
109
- return io ;
109
+ if (return_io )
110
+ return io ;
111
+ else
112
+ return result ;
110
113
}
111
114
else {
112
- return Qfalse ;
115
+ return Qfalse ;
113
116
}
114
117
}
115
118
#endif
@@ -137,15 +140,15 @@ io_ready_p(VALUE io)
137
140
if (rb_io_read_pending (fptr )) return Qtrue ;
138
141
139
142
#ifndef HAVE_RB_IO_WAIT
140
- if (wait_for_single_fd (fptr , RB_WAITFD_IN , & tv ))
141
- return Qtrue ;
143
+ return wait_for_single_fd (fptr , RB_WAITFD_IN , & tv ) ? Qtrue : Qfalse ;
142
144
#else
143
- if (RTEST (io_wait_event (io , RUBY_IO_READABLE , RB_INT2NUM (0 ))))
144
- return Qtrue ;
145
+ return io_wait_event (io , RUBY_IO_READABLE , RB_INT2NUM (0 ), 1 );
145
146
#endif
146
- return Qfalse ;
147
147
}
148
148
149
+ // Ruby 3.2+ can define these methods. This macro indicates that case.
150
+ #ifndef RUBY_IO_WAIT_METHODS
151
+
149
152
/*
150
153
* call-seq:
151
154
* io.wait_readable -> truthy or falsy
@@ -184,7 +187,7 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
184
187
rb_check_arity (argc , 0 , 1 );
185
188
VALUE timeout = (argc == 1 ? argv [0 ] : Qnil );
186
189
187
- return io_wait_event (io , RUBY_IO_READABLE , timeout );
190
+ return io_wait_event (io , RUBY_IO_READABLE , timeout , 1 );
188
191
#endif
189
192
}
190
193
@@ -220,7 +223,7 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
220
223
rb_check_arity (argc , 0 , 1 );
221
224
VALUE timeout = (argc == 1 ? argv [0 ] : Qnil );
222
225
223
- return io_wait_event (io , RUBY_IO_WRITABLE , timeout );
226
+ return io_wait_event (io , RUBY_IO_WRITABLE , timeout , 1 );
224
227
#endif
225
228
}
226
229
@@ -231,7 +234,8 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
231
234
* io.wait_priority(timeout) -> truthy or falsy
232
235
*
233
236
* Waits until IO is priority and returns a truthy value or a falsy
234
- * value when times out.
237
+ * value when times out. Priority data is sent and received using
238
+ * the Socket::MSG_OOB flag and is typically limited to streams.
235
239
*
236
240
* You must require 'io/wait' to use this method.
237
241
*/
@@ -248,7 +252,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
248
252
rb_check_arity (argc , 0 , 1 );
249
253
VALUE timeout = argc == 1 ? argv [0 ] : Qnil ;
250
254
251
- return io_wait_event (io , RUBY_IO_PRIORITY , timeout );
255
+ return io_wait_event (io , RUBY_IO_PRIORITY , timeout , 1 );
252
256
}
253
257
#endif
254
258
@@ -286,10 +290,22 @@ wait_mode_sym(VALUE mode)
286
290
return 0 ;
287
291
}
288
292
293
+ #ifdef HAVE_RB_IO_WAIT
294
+ static inline rb_io_event_t
295
+ io_event_from_value (VALUE value )
296
+ {
297
+ int events = RB_NUM2INT (value );
298
+
299
+ if (events <= 0 ) rb_raise (rb_eArgError , "Events must be positive integer!" );
300
+
301
+ return events ;
302
+ }
303
+ #endif
304
+
289
305
/*
290
306
* call-seq:
291
- * io.wait(events, timeout) -> truthy or falsy
292
- * io.wait(timeout = nil, mode = :read) -> truthy or falsy.
307
+ * io.wait(events, timeout) -> event mask, false or nil
308
+ * io.wait(timeout = nil, mode = :read) -> self, true, or false
293
309
*
294
310
* Waits until the IO becomes ready for the specified events and returns the
295
311
* subset of events that become ready, or a falsy value when times out.
@@ -335,43 +351,59 @@ io_wait(int argc, VALUE *argv, VALUE io)
335
351
#else
336
352
VALUE timeout = Qundef ;
337
353
rb_io_event_t events = 0 ;
354
+ int return_io = 0 ;
338
355
356
+ // The documented signature for this method is actually incorrect.
357
+ // A single timeout is allowed in any position, and multiple symbols can be given.
358
+ // Whether this is intentional or not, I don't know, and as such I consider this to
359
+ // be a legacy/slow path.
339
360
if (argc != 2 || (RB_SYMBOL_P (argv [0 ]) || RB_SYMBOL_P (argv [1 ]))) {
340
- for (int i = 0 ; i < argc ; i += 1 ) {
341
- if (RB_SYMBOL_P (argv [i ])) {
342
- events |= wait_mode_sym (argv [i ]);
343
- }
344
- else if (timeout == Qundef ) {
345
- rb_time_interval (timeout = argv [i ]);
346
- }
347
- else {
348
- rb_raise (rb_eArgError , "timeout given more than once" );
349
- }
350
- }
351
- if (timeout == Qundef ) timeout = Qnil ;
361
+ // We'd prefer to return the actual mask, but this form would return the io itself:
362
+ return_io = 1 ;
363
+
364
+ // Slow/messy path:
365
+ for (int i = 0 ; i < argc ; i += 1 ) {
366
+ if (RB_SYMBOL_P (argv [i ])) {
367
+ events |= wait_mode_sym (argv [i ]);
368
+ }
369
+ else if (timeout == Qundef ) {
370
+ rb_time_interval (timeout = argv [i ]);
371
+ }
372
+ else {
373
+ rb_raise (rb_eArgError , "timeout given more than once" );
374
+ }
375
+ }
376
+
377
+ if (timeout == Qundef ) timeout = Qnil ;
378
+
379
+ if (events == 0 ) {
380
+ events = RUBY_IO_READABLE ;
381
+ }
352
382
}
353
- else /* argc == 2 */ {
354
- events = RB_NUM2UINT (argv [0 ]);
355
- timeout = argv [1 ];
356
- }
357
-
358
- if (events == 0 ) {
359
- events = RUBY_IO_READABLE ;
383
+ else /* argc == 2 and neither are symbols */ {
384
+ // This is the fast path:
385
+ events = io_event_from_value (argv [0 ]);
386
+ timeout = argv [1 ];
360
387
}
361
388
362
389
if (events & RUBY_IO_READABLE ) {
363
- rb_io_t * fptr = NULL ;
364
- RB_IO_POINTER (io , fptr );
365
-
366
- if (rb_io_read_pending (fptr )) {
367
- return Qtrue ;
368
- }
390
+ rb_io_t * fptr = NULL ;
391
+ RB_IO_POINTER (io , fptr );
392
+
393
+ if (rb_io_read_pending (fptr )) {
394
+ // This was the original behaviour:
395
+ if (return_io ) return Qtrue ;
396
+ // New behaviour always returns an event mask:
397
+ else return RB_INT2NUM (RUBY_IO_READABLE );
398
+ }
369
399
}
370
400
371
- return io_wait_event (io , events , timeout );
401
+ return io_wait_event (io , events , timeout , return_io );
372
402
#endif
373
403
}
374
404
405
+ #endif /* RUBY_IO_WAIT_METHODS */
406
+
375
407
/*
376
408
* IO wait methods
377
409
*/
@@ -386,11 +418,13 @@ Init_wait(void)
386
418
rb_define_method (rb_cIO , "nread" , io_nread , 0 );
387
419
rb_define_method (rb_cIO , "ready?" , io_ready_p , 0 );
388
420
421
+ #ifndef RUBY_IO_WAIT_METHODS
389
422
rb_define_method (rb_cIO , "wait" , io_wait , -1 );
390
423
391
424
rb_define_method (rb_cIO , "wait_readable" , io_wait_readable , -1 );
392
425
rb_define_method (rb_cIO , "wait_writable" , io_wait_writable , -1 );
393
426
#ifdef HAVE_RB_IO_WAIT
394
427
rb_define_method (rb_cIO , "wait_priority" , io_wait_priority , -1 );
395
428
#endif
429
+ #endif
396
430
}
0 commit comments