io-wait 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/ext/io/wait/wait.c +98 -69
  3. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43e7f91045efd73e51af1a6e055afe646fc95d1b7c1a154453d915e6a213d223
4
- data.tar.gz: 4d542bfb7bde6053c4069f451d41f39e05b77d0ebab5514532f601466ca57bba
3
+ metadata.gz: 630936f8af6e2cf9265ebff0794cab1daf10048933460b71306486aecb92a85a
4
+ data.tar.gz: 153bc0301fdb8fce6f4983d45879364509bb6534a81775d98e5f61b5ffe1923e
5
5
  SHA512:
6
- metadata.gz: f78dc92e4500c196b69d87fb47f13f426f4a2d9b8532e69027d3c96a8dd93514d08c77adc421b8d3cac2e0aaf2f80d92327c98d95969a9816111b41c373fe10a
7
- data.tar.gz: 4b2b4af88c93ddc7d12d1060f6f638aab6fc75178a32fe9810478a5b95e27575cbe1054c1e46964b7ca1eec1269f47b64bf823a990472363cb97c75236b4a438
6
+ metadata.gz: 07e0a9997d9e8dd84368feb0fdcd681282d7c583aea8d03d90abf031d6474224aa7a6f61050de11a03750cc0e20ba5759ac4eca28aae07891a778ef82cef24c6
7
+ data.tar.gz: 7294e823b4536cded39faead19916b437e4a8a4d398e35917c81e84d4618d5f99bd414aa9f6989cfad4bfb8bf0721fb7934b083a72576a7e95a60d7fcf35e853
data/ext/io/wait/wait.c CHANGED
@@ -41,22 +41,17 @@
41
41
  #endif
42
42
 
43
43
  #ifndef HAVE_RB_IO_WAIT
44
- static VALUE io_ready_p _((VALUE io));
45
- static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
46
- static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
47
- void Init_wait _((void));
48
-
49
44
  static struct timeval *
50
45
  get_timeout(int argc, VALUE *argv, struct timeval *timerec)
51
46
  {
52
47
  VALUE timeout = Qnil;
53
48
  rb_check_arity(argc, 0, 1);
54
49
  if (!argc || NIL_P(timeout = argv[0])) {
55
- return NULL;
50
+ return NULL;
56
51
  }
57
52
  else {
58
- *timerec = rb_time_interval(timeout);
59
- return timerec;
53
+ *timerec = rb_time_interval(timeout);
54
+ return timerec;
60
55
  }
61
56
  }
62
57
 
@@ -65,7 +60,7 @@ wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
65
60
  {
66
61
  int i = rb_wait_for_single_fd(fptr->fd, events, tv);
67
62
  if (i < 0)
68
- rb_sys_fail(0);
63
+ rb_sys_fail(0);
69
64
  rb_io_check_closed(fptr);
70
65
  return (i & events);
71
66
  }
@@ -100,21 +95,24 @@ io_nread(VALUE io)
100
95
 
101
96
  #ifdef HAVE_RB_IO_WAIT
102
97
  static VALUE
103
- io_wait_event(VALUE io, int event, VALUE timeout)
98
+ io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
104
99
  {
105
100
  VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
106
101
 
107
102
  if (!RB_TEST(result)) {
108
- return Qnil;
103
+ return Qnil;
109
104
  }
110
105
 
111
106
  int mask = RB_NUM2INT(result);
112
107
 
113
108
  if (mask & event) {
114
- return io;
109
+ if (return_io)
110
+ return io;
111
+ else
112
+ return result;
115
113
  }
116
114
  else {
117
- return Qfalse;
115
+ return Qfalse;
118
116
  }
119
117
  }
120
118
  #endif
@@ -142,15 +140,15 @@ io_ready_p(VALUE io)
142
140
  if (rb_io_read_pending(fptr)) return Qtrue;
143
141
 
144
142
  #ifndef HAVE_RB_IO_WAIT
145
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
146
- return Qtrue;
143
+ return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
147
144
  #else
148
- if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0))))
149
- return Qtrue;
145
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
150
146
  #endif
151
- return Qfalse;
152
147
  }
153
148
 
149
+ /* Ruby 3.2+ can define these methods. This macro indicates that case. */
150
+ #ifndef RUBY_IO_WAIT_METHODS
151
+
154
152
  /*
155
153
  * call-seq:
156
154
  * io.wait_readable -> truthy or falsy
@@ -182,14 +180,14 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
182
180
 
183
181
  #ifndef HAVE_RB_IO_WAIT
184
182
  if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
185
- return io;
183
+ return io;
186
184
  }
187
185
  return Qnil;
188
186
  #else
189
187
  rb_check_arity(argc, 0, 1);
190
188
  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
191
189
 
192
- return io_wait_event(io, RUBY_IO_READABLE, timeout);
190
+ return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
193
191
  #endif
194
192
  }
195
193
 
@@ -218,14 +216,14 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
218
216
  #ifndef HAVE_RB_IO_WAIT
219
217
  tv = get_timeout(argc, argv, &timerec);
220
218
  if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
221
- return io;
219
+ return io;
222
220
  }
223
221
  return Qnil;
224
222
  #else
225
223
  rb_check_arity(argc, 0, 1);
226
224
  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
227
225
 
228
- return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
226
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
229
227
  #endif
230
228
  }
231
229
 
@@ -236,7 +234,8 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
236
234
  * io.wait_priority(timeout) -> truthy or falsy
237
235
  *
238
236
  * Waits until IO is priority and returns a truthy value or a falsy
239
- * 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.
240
239
  *
241
240
  * You must require 'io/wait' to use this method.
242
241
  */
@@ -253,7 +252,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
253
252
  rb_check_arity(argc, 0, 1);
254
253
  VALUE timeout = argc == 1 ? argv[0] : Qnil;
255
254
 
256
- return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
255
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
257
256
  }
258
257
  #endif
259
258
 
@@ -261,40 +260,52 @@ static int
261
260
  wait_mode_sym(VALUE mode)
262
261
  {
263
262
  if (mode == ID2SYM(rb_intern("r"))) {
264
- return RB_WAITFD_IN;
263
+ return RB_WAITFD_IN;
265
264
  }
266
265
  if (mode == ID2SYM(rb_intern("read"))) {
267
- return RB_WAITFD_IN;
266
+ return RB_WAITFD_IN;
268
267
  }
269
268
  if (mode == ID2SYM(rb_intern("readable"))) {
270
- return RB_WAITFD_IN;
269
+ return RB_WAITFD_IN;
271
270
  }
272
271
  if (mode == ID2SYM(rb_intern("w"))) {
273
- return RB_WAITFD_OUT;
272
+ return RB_WAITFD_OUT;
274
273
  }
275
274
  if (mode == ID2SYM(rb_intern("write"))) {
276
- return RB_WAITFD_OUT;
275
+ return RB_WAITFD_OUT;
277
276
  }
278
277
  if (mode == ID2SYM(rb_intern("writable"))) {
279
- return RB_WAITFD_OUT;
278
+ return RB_WAITFD_OUT;
280
279
  }
281
280
  if (mode == ID2SYM(rb_intern("rw"))) {
282
- return RB_WAITFD_IN|RB_WAITFD_OUT;
281
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
283
282
  }
284
283
  if (mode == ID2SYM(rb_intern("read_write"))) {
285
- return RB_WAITFD_IN|RB_WAITFD_OUT;
284
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
286
285
  }
287
286
  if (mode == ID2SYM(rb_intern("readable_writable"))) {
288
- return RB_WAITFD_IN|RB_WAITFD_OUT;
287
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
289
288
  }
290
289
  rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
291
290
  return 0;
292
291
  }
293
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
+
294
305
  /*
295
306
  * call-seq:
296
- * io.wait(events, timeout) -> truthy or falsy
297
- * 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
298
309
  *
299
310
  * Waits until the IO becomes ready for the specified events and returns the
300
311
  * subset of events that become ready, or a falsy value when times out.
@@ -322,61 +333,77 @@ io_wait(int argc, VALUE *argv, VALUE io)
322
333
 
323
334
  GetOpenFile(io, fptr);
324
335
  for (i = 0; i < argc; ++i) {
325
- if (SYMBOL_P(argv[i])) {
326
- event |= wait_mode_sym(argv[i]);
327
- }
328
- else {
329
- *(tv = &timerec) = rb_time_interval(argv[i]);
330
- }
336
+ if (SYMBOL_P(argv[i])) {
337
+ event |= wait_mode_sym(argv[i]);
338
+ }
339
+ else {
340
+ *(tv = &timerec) = rb_time_interval(argv[i]);
341
+ }
331
342
  }
332
343
  /* rb_time_interval() and might_mode() might convert the argument */
333
344
  rb_io_check_closed(fptr);
334
345
  if (!event) event = RB_WAITFD_IN;
335
346
  if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
336
- return Qtrue;
347
+ return Qtrue;
337
348
  if (wait_for_single_fd(fptr, event, tv))
338
- return io;
349
+ return io;
339
350
  return Qnil;
340
351
  #else
341
352
  VALUE timeout = Qundef;
342
353
  rb_io_event_t events = 0;
354
+ int i, return_io = 0;
343
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. */
344
360
  if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
345
- for (int i = 0; i < argc; i += 1) {
346
- if (RB_SYMBOL_P(argv[i])) {
347
- events |= wait_mode_sym(argv[i]);
348
- }
349
- else if (timeout == Qundef) {
350
- rb_time_interval(timeout = argv[i]);
351
- }
352
- else {
353
- rb_raise(rb_eArgError, "timeout given more than once");
354
- }
355
- }
356
- 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 (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
+ }
357
382
  }
358
- else /* argc == 2 */ {
359
- events = RB_NUM2UINT(argv[0]);
360
- timeout = argv[1];
361
- }
362
-
363
- if (events == 0) {
364
- 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];
365
387
  }
366
388
 
367
389
  if (events & RUBY_IO_READABLE) {
368
- rb_io_t *fptr = NULL;
369
- RB_IO_POINTER(io, fptr);
370
-
371
- if (rb_io_read_pending(fptr)) {
372
- return Qtrue;
373
- }
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
+ }
374
399
  }
375
400
 
376
- return io_wait_event(io, events, timeout);
401
+ return io_wait_event(io, events, timeout, return_io);
377
402
  #endif
378
403
  }
379
404
 
405
+ #endif /* RUBY_IO_WAIT_METHODS */
406
+
380
407
  /*
381
408
  * IO wait methods
382
409
  */
@@ -391,6 +418,7 @@ Init_wait(void)
391
418
  rb_define_method(rb_cIO, "nread", io_nread, 0);
392
419
  rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
393
420
 
421
+ #ifndef RUBY_IO_WAIT_METHODS
394
422
  rb_define_method(rb_cIO, "wait", io_wait, -1);
395
423
 
396
424
  rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
@@ -398,4 +426,5 @@ Init_wait(void)
398
426
  #ifdef HAVE_RB_IO_WAIT
399
427
  rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
400
428
  #endif
429
+ #endif
401
430
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-wait
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-05-09 00:00:00.000000000 Z
12
+ date: 2022-12-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Waits until IO is readable or writable without blocking.
15
15
  email: