io-wait 0.2.3 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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.