io-wait 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43e7f91045efd73e51af1a6e055afe646fc95d1b7c1a154453d915e6a213d223
4
- data.tar.gz: 4d542bfb7bde6053c4069f451d41f39e05b77d0ebab5514532f601466ca57bba
3
+ metadata.gz: ab2e90fe2ac7d5df2d629e3ccd501b8c01570fadd3eeee5d42709e55deb26ec6
4
+ data.tar.gz: 12663accc0c74fb25368e47a87fbc7a5b4f06ccd7435ee1ab4528e51b4dca843
5
5
  SHA512:
6
- metadata.gz: f78dc92e4500c196b69d87fb47f13f426f4a2d9b8532e69027d3c96a8dd93514d08c77adc421b8d3cac2e0aaf2f80d92327c98d95969a9816111b41c373fe10a
7
- data.tar.gz: 4b2b4af88c93ddc7d12d1060f6f638aab6fc75178a32fe9810478a5b95e27575cbe1054c1e46964b7ca1eec1269f47b64bf823a990472363cb97c75236b4a438
6
+ metadata.gz: 1bc887d4119a7c39978294b99d6bc2affbc0124236ec4062fe439ffbfa64db295ec4de180a1db16ad2c481927a72f046def66e34dae9cca49157ccd25a8b82e4
7
+ data.tar.gz: 1b237ca1a3f74ff1208059f49061df665ff4a78f8da89d9b7ffbb9a57cd9205ffbb848fb583704fafad66954df7f2481d9a145e1d68591c31d11ab8fff1b2dbe
data/Gemfile CHANGED
@@ -7,5 +7,6 @@ group :development do
7
7
  gem "rake"
8
8
  gem "rake-compiler"
9
9
  gem "test-unit"
10
+ gem "test-unit-ruby-core"
10
11
  gem 'ruby-maven', :platforms => :jruby
11
12
  end
@@ -6,6 +6,7 @@ if RUBY_VERSION < "2.6"
6
6
  else
7
7
  target = "io/wait"
8
8
  have_func("rb_io_wait")
9
+ have_func("rb_io_descriptor")
9
10
  unless macro_defined?("DOSISH", "#include <ruby.h>")
10
11
  have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
11
12
  fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
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
  }
@@ -92,29 +87,39 @@ io_nread(VALUE io)
92
87
  rb_io_check_readable(fptr);
93
88
  len = rb_io_read_pending(fptr);
94
89
  if (len > 0) return INT2FIX(len);
95
- if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
96
- if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
90
+
91
+ #ifdef HAVE_RB_IO_DESCRIPTOR
92
+ int fd = rb_io_descriptor(io);
93
+ #else
94
+ int fd = fptr->fd;
95
+ #endif
96
+
97
+ if (!FIONREAD_POSSIBLE_P(fd)) return INT2FIX(0);
98
+ if (ioctl(fd, FIONREAD, &n)) return INT2FIX(0);
97
99
  if (n > 0) return ioctl_arg2num(n);
98
100
  return INT2FIX(0);
99
101
  }
100
102
 
101
103
  #ifdef HAVE_RB_IO_WAIT
102
104
  static VALUE
103
- io_wait_event(VALUE io, int event, VALUE timeout)
105
+ io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
104
106
  {
105
107
  VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
106
108
 
107
109
  if (!RB_TEST(result)) {
108
- return Qnil;
110
+ return Qnil;
109
111
  }
110
112
 
111
113
  int mask = RB_NUM2INT(result);
112
114
 
113
115
  if (mask & event) {
114
- return io;
116
+ if (return_io)
117
+ return io;
118
+ else
119
+ return result;
115
120
  }
116
121
  else {
117
- return Qfalse;
122
+ return Qfalse;
118
123
  }
119
124
  }
120
125
  #endif
@@ -142,15 +147,15 @@ io_ready_p(VALUE io)
142
147
  if (rb_io_read_pending(fptr)) return Qtrue;
143
148
 
144
149
  #ifndef HAVE_RB_IO_WAIT
145
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
146
- return Qtrue;
150
+ return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
147
151
  #else
148
- if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0))))
149
- return Qtrue;
152
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
150
153
  #endif
151
- return Qfalse;
152
154
  }
153
155
 
156
+ /* Ruby 3.2+ can define these methods. This macro indicates that case. */
157
+ #ifndef RUBY_IO_WAIT_METHODS
158
+
154
159
  /*
155
160
  * call-seq:
156
161
  * io.wait_readable -> truthy or falsy
@@ -182,14 +187,14 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
182
187
 
183
188
  #ifndef HAVE_RB_IO_WAIT
184
189
  if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
185
- return io;
190
+ return io;
186
191
  }
187
192
  return Qnil;
188
193
  #else
189
194
  rb_check_arity(argc, 0, 1);
190
195
  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
191
196
 
192
- return io_wait_event(io, RUBY_IO_READABLE, timeout);
197
+ return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
193
198
  #endif
194
199
  }
195
200
 
@@ -218,14 +223,14 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
218
223
  #ifndef HAVE_RB_IO_WAIT
219
224
  tv = get_timeout(argc, argv, &timerec);
220
225
  if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
221
- return io;
226
+ return io;
222
227
  }
223
228
  return Qnil;
224
229
  #else
225
230
  rb_check_arity(argc, 0, 1);
226
231
  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
227
232
 
228
- return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
233
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
229
234
  #endif
230
235
  }
231
236
 
@@ -236,7 +241,8 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
236
241
  * io.wait_priority(timeout) -> truthy or falsy
237
242
  *
238
243
  * Waits until IO is priority and returns a truthy value or a falsy
239
- * value when times out.
244
+ * value when times out. Priority data is sent and received using
245
+ * the Socket::MSG_OOB flag and is typically limited to streams.
240
246
  *
241
247
  * You must require 'io/wait' to use this method.
242
248
  */
@@ -253,7 +259,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
253
259
  rb_check_arity(argc, 0, 1);
254
260
  VALUE timeout = argc == 1 ? argv[0] : Qnil;
255
261
 
256
- return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
262
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
257
263
  }
258
264
  #endif
259
265
 
@@ -261,40 +267,52 @@ static int
261
267
  wait_mode_sym(VALUE mode)
262
268
  {
263
269
  if (mode == ID2SYM(rb_intern("r"))) {
264
- return RB_WAITFD_IN;
270
+ return RB_WAITFD_IN;
265
271
  }
266
272
  if (mode == ID2SYM(rb_intern("read"))) {
267
- return RB_WAITFD_IN;
273
+ return RB_WAITFD_IN;
268
274
  }
269
275
  if (mode == ID2SYM(rb_intern("readable"))) {
270
- return RB_WAITFD_IN;
276
+ return RB_WAITFD_IN;
271
277
  }
272
278
  if (mode == ID2SYM(rb_intern("w"))) {
273
- return RB_WAITFD_OUT;
279
+ return RB_WAITFD_OUT;
274
280
  }
275
281
  if (mode == ID2SYM(rb_intern("write"))) {
276
- return RB_WAITFD_OUT;
282
+ return RB_WAITFD_OUT;
277
283
  }
278
284
  if (mode == ID2SYM(rb_intern("writable"))) {
279
- return RB_WAITFD_OUT;
285
+ return RB_WAITFD_OUT;
280
286
  }
281
287
  if (mode == ID2SYM(rb_intern("rw"))) {
282
- return RB_WAITFD_IN|RB_WAITFD_OUT;
288
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
283
289
  }
284
290
  if (mode == ID2SYM(rb_intern("read_write"))) {
285
- return RB_WAITFD_IN|RB_WAITFD_OUT;
291
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
286
292
  }
287
293
  if (mode == ID2SYM(rb_intern("readable_writable"))) {
288
- return RB_WAITFD_IN|RB_WAITFD_OUT;
294
+ return RB_WAITFD_IN|RB_WAITFD_OUT;
289
295
  }
290
296
  rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
291
297
  return 0;
292
298
  }
293
299
 
300
+ #ifdef HAVE_RB_IO_WAIT
301
+ static inline rb_io_event_t
302
+ io_event_from_value(VALUE value)
303
+ {
304
+ int events = RB_NUM2INT(value);
305
+
306
+ if (events <= 0) rb_raise(rb_eArgError, "Events must be positive integer!");
307
+
308
+ return events;
309
+ }
310
+ #endif
311
+
294
312
  /*
295
313
  * call-seq:
296
- * io.wait(events, timeout) -> truthy or falsy
297
- * io.wait(timeout = nil, mode = :read) -> truthy or falsy.
314
+ * io.wait(events, timeout) -> event mask, false or nil
315
+ * io.wait(timeout = nil, mode = :read) -> self, true, or false
298
316
  *
299
317
  * Waits until the IO becomes ready for the specified events and returns the
300
318
  * subset of events that become ready, or a falsy value when times out.
@@ -322,61 +340,77 @@ io_wait(int argc, VALUE *argv, VALUE io)
322
340
 
323
341
  GetOpenFile(io, fptr);
324
342
  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
- }
343
+ if (SYMBOL_P(argv[i])) {
344
+ event |= wait_mode_sym(argv[i]);
345
+ }
346
+ else {
347
+ *(tv = &timerec) = rb_time_interval(argv[i]);
348
+ }
331
349
  }
332
350
  /* rb_time_interval() and might_mode() might convert the argument */
333
351
  rb_io_check_closed(fptr);
334
352
  if (!event) event = RB_WAITFD_IN;
335
353
  if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
336
- return Qtrue;
354
+ return Qtrue;
337
355
  if (wait_for_single_fd(fptr, event, tv))
338
- return io;
356
+ return io;
339
357
  return Qnil;
340
358
  #else
341
359
  VALUE timeout = Qundef;
342
360
  rb_io_event_t events = 0;
361
+ int i, return_io = 0;
343
362
 
363
+ /* The documented signature for this method is actually incorrect.
364
+ * A single timeout is allowed in any position, and multiple symbols can be given.
365
+ * Whether this is intentional or not, I don't know, and as such I consider this to
366
+ * be a legacy/slow path. */
344
367
  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;
368
+ /* We'd prefer to return the actual mask, but this form would return the io itself: */
369
+ return_io = 1;
370
+
371
+ /* Slow/messy path: */
372
+ for (i = 0; i < argc; i += 1) {
373
+ if (RB_SYMBOL_P(argv[i])) {
374
+ events |= wait_mode_sym(argv[i]);
375
+ }
376
+ else if (timeout == Qundef) {
377
+ rb_time_interval(timeout = argv[i]);
378
+ }
379
+ else {
380
+ rb_raise(rb_eArgError, "timeout given more than once");
381
+ }
382
+ }
383
+
384
+ if (timeout == Qundef) timeout = Qnil;
385
+
386
+ if (events == 0) {
387
+ events = RUBY_IO_READABLE;
388
+ }
357
389
  }
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;
390
+ else /* argc == 2 and neither are symbols */ {
391
+ /* This is the fast path: */
392
+ events = io_event_from_value(argv[0]);
393
+ timeout = argv[1];
365
394
  }
366
395
 
367
396
  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
- }
397
+ rb_io_t *fptr = NULL;
398
+ RB_IO_POINTER(io, fptr);
399
+
400
+ if (rb_io_read_pending(fptr)) {
401
+ /* This was the original behaviour: */
402
+ if (return_io) return Qtrue;
403
+ /* New behaviour always returns an event mask: */
404
+ else return RB_INT2NUM(RUBY_IO_READABLE);
405
+ }
374
406
  }
375
407
 
376
- return io_wait_event(io, events, timeout);
408
+ return io_wait_event(io, events, timeout, return_io);
377
409
  #endif
378
410
  }
379
411
 
412
+ #endif /* RUBY_IO_WAIT_METHODS */
413
+
380
414
  /*
381
415
  * IO wait methods
382
416
  */
@@ -391,6 +425,7 @@ Init_wait(void)
391
425
  rb_define_method(rb_cIO, "nread", io_nread, 0);
392
426
  rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
393
427
 
428
+ #ifndef RUBY_IO_WAIT_METHODS
394
429
  rb_define_method(rb_cIO, "wait", io_wait, -1);
395
430
 
396
431
  rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
@@ -398,4 +433,5 @@ Init_wait(void)
398
433
  #ifdef HAVE_RB_IO_WAIT
399
434
  rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
400
435
  #endif
436
+ #endif
401
437
  }
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.1
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: 2023-12-13 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Waits until IO is readable or writable without blocking.
15
15
  email:
@@ -48,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
48
48
  - !ruby/object:Gem::Version
49
49
  version: '0'
50
50
  requirements: []
51
- rubygems_version: 3.4.0.dev
51
+ rubygems_version: 3.5.0.dev
52
52
  signing_key:
53
53
  specification_version: 4
54
54
  summary: Waits until IO is readable or writable without blocking.