io-wait 0.3.5 → 0.4.0

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: 207c3560ea3e98dc4f739d1f77be51dbf7b8988315746f0864407b63e2d68c06
4
- data.tar.gz: 7857a7feddd706523d2456e9d1a7c3a2d4c3cdfc04e732c96e2475fc769012d3
3
+ metadata.gz: e60418360dcf692b36cb2cf2ccb908dde272503ef0d15cd39ca9b2f49dbbc1df
4
+ data.tar.gz: 3eed0651def11e51177648806ca564a24a783bfa7365c78039b7ef37808cac9e
5
5
  SHA512:
6
- metadata.gz: 79f5aa4a9656ed615444268d31b6759a0aff527bfa5cec973274ac7a1ac3b1982c37059bd43486951a613a9a254a4c1f10d1e1e83b17cf2731a643dee6f3f1e5
7
- data.tar.gz: 82b9a23f2a3c98f337b2a94fee0f4d27de91dc825e79ac08c9e314d3325b2eaaa1e5e60d04e91fa6a18a8f37a3f33f76f1d050d857ff9dae6e68702786cc2a03
6
+ metadata.gz: 1e772560133ce1309fc71e8c27d7591fe44c6d956953b002a7bf13fc38529d4d41edde4abccebea90b27853ded7fb6727b991ea2d3439fe45359791f85025f88
7
+ data.tar.gz: 4c448bcca53322ab1a7ccb06f6dab9c5e3d59eb288a97cd74d45b3981129d899295044211a2062bcad45df57332679dfe43f64d56ca0a5df56960d179f62582a
@@ -1,21 +1,4 @@
1
1
  # frozen_string_literal: false
2
2
  require 'mkmf'
3
3
 
4
- target = "io/wait"
5
- have_func("rb_io_wait", "ruby/io.h")
6
- have_func("rb_io_descriptor", "ruby/io.h")
7
- unless macro_defined?("DOSISH", "#include <ruby.h>")
8
- have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
9
- fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
10
- have_macro("FIONREAD", [h, ioctl_h].compact)
11
- end
12
- if fionread
13
- $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
14
- create_makefile(target)
15
- end
16
- else
17
- if have_func("rb_w32_ioctlsocket", "ruby.h")
18
- have_func("rb_w32_is_socket", "ruby.h")
19
- create_makefile(target)
20
- end
21
- end
4
+ create_makefile("io/wait")
data/ext/io/wait/wait.c CHANGED
@@ -11,427 +11,13 @@
11
11
 
12
12
  **********************************************************************/
13
13
 
14
- #include "ruby.h"
15
- #include "ruby/io.h"
16
-
17
- #include <sys/types.h>
18
- #if defined(HAVE_UNISTD_H) && (defined(__sun))
19
- #include <unistd.h>
20
- #endif
21
- #if defined(HAVE_SYS_IOCTL_H)
22
- #include <sys/ioctl.h>
23
- #endif
24
- #if defined(FIONREAD_HEADER)
25
- #include FIONREAD_HEADER
26
- #endif
27
-
28
- #ifdef HAVE_RB_W32_IOCTLSOCKET
29
- #define ioctl ioctlsocket
30
- #define ioctl_arg u_long
31
- #define ioctl_arg2num(i) ULONG2NUM(i)
32
- #else
33
- #define ioctl_arg int
34
- #define ioctl_arg2num(i) INT2NUM(i)
35
- #endif
36
-
37
- #ifdef HAVE_RB_W32_IS_SOCKET
38
- #define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
39
- #else
40
- #define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
41
- #endif
42
-
43
- #ifndef HAVE_RB_IO_WAIT
44
- static struct timeval *
45
- get_timeout(int argc, VALUE *argv, struct timeval *timerec)
46
- {
47
- VALUE timeout = Qnil;
48
- rb_check_arity(argc, 0, 1);
49
- if (!argc || NIL_P(timeout = argv[0])) {
50
- return NULL;
51
- }
52
- else {
53
- *timerec = rb_time_interval(timeout);
54
- return timerec;
55
- }
56
- }
57
-
58
- static int
59
- wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
60
- {
61
- int i = rb_wait_for_single_fd(fptr->fd, events, tv);
62
- if (i < 0)
63
- rb_sys_fail(0);
64
- rb_io_check_closed(fptr);
65
- return (i & events);
66
- }
67
- #endif
68
-
69
- /*
70
- * call-seq:
71
- * io.nread -> int
72
- *
73
- * Returns number of bytes that can be read without blocking.
74
- * Returns zero if no information available.
75
- *
76
- * You must require 'io/wait' to use this method.
77
- */
78
-
79
- static VALUE
80
- io_nread(VALUE io)
81
- {
82
- rb_io_t *fptr;
83
- int len;
84
- ioctl_arg n;
85
-
86
- GetOpenFile(io, fptr);
87
- rb_io_check_char_readable(fptr);
88
- len = rb_io_read_pending(fptr);
89
- if (len > 0) return INT2FIX(len);
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);
99
- if (n > 0) return ioctl_arg2num(n);
100
- return INT2FIX(0);
101
- }
102
-
103
- #ifdef HAVE_RB_IO_WAIT
104
- static VALUE
105
- io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
106
- {
107
- VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
108
-
109
- if (!RB_TEST(result)) {
110
- return Qnil;
111
- }
112
-
113
- int mask = RB_NUM2INT(result);
114
-
115
- if (mask & event) {
116
- if (return_io)
117
- return io;
118
- else
119
- return result;
120
- }
121
- else {
122
- return Qfalse;
123
- }
124
- }
125
- #endif
126
-
127
- /*
128
- * call-seq:
129
- * io.ready? -> truthy or falsy
130
- *
131
- * Returns a truthy value if input available without blocking, or a
132
- * falsy value.
133
- *
134
- * You must require 'io/wait' to use this method.
135
- */
136
-
137
- static VALUE
138
- io_ready_p(VALUE io)
139
- {
140
- rb_io_t *fptr;
141
- #ifndef HAVE_RB_IO_WAIT
142
- struct timeval tv = {0, 0};
143
- #endif
144
-
145
- GetOpenFile(io, fptr);
146
- rb_io_check_char_readable(fptr);
147
- if (rb_io_read_pending(fptr)) return Qtrue;
148
-
149
- #ifndef HAVE_RB_IO_WAIT
150
- return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
151
- #else
152
- return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
153
- #endif
154
- }
155
-
156
- /* Ruby 3.2+ can define these methods. This macro indicates that case. */
157
- #ifndef RUBY_IO_WAIT_METHODS
158
-
159
- /*
160
- * call-seq:
161
- * io.wait_readable -> truthy or falsy
162
- * io.wait_readable(timeout) -> truthy or falsy
163
- *
164
- * Waits until IO is readable and returns a truthy value, or a falsy
165
- * value when times out. Returns a truthy value immediately when
166
- * buffered data is available.
167
- *
168
- * You must require 'io/wait' to use this method.
169
- */
170
-
171
- static VALUE
172
- io_wait_readable(int argc, VALUE *argv, VALUE io)
173
- {
174
- rb_io_t *fptr;
175
- #ifndef HAVE_RB_IO_WAIT
176
- struct timeval timerec;
177
- struct timeval *tv;
178
- #endif
179
-
180
- GetOpenFile(io, fptr);
181
- rb_io_check_char_readable(fptr);
182
-
183
- #ifndef HAVE_RB_IO_WAIT
184
- tv = get_timeout(argc, argv, &timerec);
185
- #endif
186
- if (rb_io_read_pending(fptr)) return Qtrue;
187
-
188
- #ifndef HAVE_RB_IO_WAIT
189
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
190
- return io;
191
- }
192
- return Qnil;
193
- #else
194
- rb_check_arity(argc, 0, 1);
195
- VALUE timeout = (argc == 1 ? argv[0] : Qnil);
196
-
197
- return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
198
- #endif
199
- }
14
+ #include "ruby.h" /* abi_version */
200
15
 
201
16
  /*
202
- * call-seq:
203
- * io.wait_writable -> truthy or falsy
204
- * io.wait_writable(timeout) -> truthy or falsy
205
- *
206
- * Waits until IO is writable and returns a truthy value or a falsy
207
- * value when times out.
208
- *
209
- * You must require 'io/wait' to use this method.
210
- */
211
- static VALUE
212
- io_wait_writable(int argc, VALUE *argv, VALUE io)
213
- {
214
- rb_io_t *fptr;
215
- #ifndef HAVE_RB_IO_WAIT
216
- struct timeval timerec;
217
- struct timeval *tv;
218
- #endif
219
-
220
- GetOpenFile(io, fptr);
221
- rb_io_check_writable(fptr);
222
-
223
- #ifndef HAVE_RB_IO_WAIT
224
- tv = get_timeout(argc, argv, &timerec);
225
- if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
226
- return io;
227
- }
228
- return Qnil;
229
- #else
230
- rb_check_arity(argc, 0, 1);
231
- VALUE timeout = (argc == 1 ? argv[0] : Qnil);
232
-
233
- return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
234
- #endif
235
- }
236
-
237
- #ifdef HAVE_RB_IO_WAIT
238
- /*
239
- * call-seq:
240
- * io.wait_priority -> truthy or falsy
241
- * io.wait_priority(timeout) -> truthy or falsy
242
- *
243
- * Waits until IO is priority and returns a truthy value or a falsy
244
- * value when times out. Priority data is sent and received using
245
- * the Socket::MSG_OOB flag and is typically limited to streams.
246
- *
247
- * You must require 'io/wait' to use this method.
248
- */
249
- static VALUE
250
- io_wait_priority(int argc, VALUE *argv, VALUE io)
251
- {
252
- rb_io_t *fptr = NULL;
253
-
254
- RB_IO_POINTER(io, fptr);
255
- rb_io_check_char_readable(fptr);
256
-
257
- if (rb_io_read_pending(fptr)) return Qtrue;
258
-
259
- rb_check_arity(argc, 0, 1);
260
- VALUE timeout = argc == 1 ? argv[0] : Qnil;
261
-
262
- return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
263
- }
264
- #endif
265
-
266
- static int
267
- wait_mode_sym(VALUE mode)
268
- {
269
- if (mode == ID2SYM(rb_intern("r"))) {
270
- return RB_WAITFD_IN;
271
- }
272
- if (mode == ID2SYM(rb_intern("read"))) {
273
- return RB_WAITFD_IN;
274
- }
275
- if (mode == ID2SYM(rb_intern("readable"))) {
276
- return RB_WAITFD_IN;
277
- }
278
- if (mode == ID2SYM(rb_intern("w"))) {
279
- return RB_WAITFD_OUT;
280
- }
281
- if (mode == ID2SYM(rb_intern("write"))) {
282
- return RB_WAITFD_OUT;
283
- }
284
- if (mode == ID2SYM(rb_intern("writable"))) {
285
- return RB_WAITFD_OUT;
286
- }
287
- if (mode == ID2SYM(rb_intern("rw"))) {
288
- return RB_WAITFD_IN|RB_WAITFD_OUT;
289
- }
290
- if (mode == ID2SYM(rb_intern("read_write"))) {
291
- return RB_WAITFD_IN|RB_WAITFD_OUT;
292
- }
293
- if (mode == ID2SYM(rb_intern("readable_writable"))) {
294
- return RB_WAITFD_IN|RB_WAITFD_OUT;
295
- }
296
- rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
297
- return 0;
298
- }
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
-
312
- /*
313
- * call-seq:
314
- * io.wait(events, timeout) -> event mask, false or nil
315
- * io.wait(*event_symbols[, timeout]) -> self, true, or false
316
- *
317
- * Waits until the IO becomes ready for the specified events and returns the
318
- * subset of events that become ready, or a falsy value when times out.
319
- *
320
- * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
321
- * +IO::PRIORITY+.
322
- *
323
- * Returns an event mask (truthy value) immediately when buffered data is
324
- * available.
325
- *
326
- * The second form: if one or more event symbols (+:read+, +:write+, or
327
- * +:read_write+) are passed, the event mask is the bit OR of the bitmask
328
- * corresponding to those symbols. In this form, +timeout+ is optional, the
329
- * order of the arguments is arbitrary, and returns +io+ if any of the
330
- * events is ready.
331
- *
332
- * You must require 'io/wait' to use this method.
333
- */
334
-
335
- static VALUE
336
- io_wait(int argc, VALUE *argv, VALUE io)
337
- {
338
- #ifndef HAVE_RB_IO_WAIT
339
- rb_io_t *fptr;
340
- struct timeval timerec;
341
- struct timeval *tv = NULL;
342
- int event = 0;
343
- int i;
344
-
345
- GetOpenFile(io, fptr);
346
- for (i = 0; i < argc; ++i) {
347
- if (SYMBOL_P(argv[i])) {
348
- event |= wait_mode_sym(argv[i]);
349
- }
350
- else {
351
- *(tv = &timerec) = rb_time_interval(argv[i]);
352
- }
353
- }
354
- /* rb_time_interval() and might_mode() might convert the argument */
355
- rb_io_check_closed(fptr);
356
- if (!event) event = RB_WAITFD_IN;
357
- if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
358
- return Qtrue;
359
- if (wait_for_single_fd(fptr, event, tv))
360
- return io;
361
- return Qnil;
362
- #else
363
- VALUE timeout = Qundef;
364
- rb_io_event_t events = 0;
365
- int i, return_io = 0;
366
-
367
- if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
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
- }
389
- }
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];
394
- }
395
-
396
- if (events & RUBY_IO_READABLE) {
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
- }
406
- }
407
-
408
- return io_wait_event(io, events, timeout, return_io);
409
- #endif
410
- }
411
-
412
- #endif /* RUBY_IO_WAIT_METHODS */
413
-
414
- /*
415
- * IO wait methods
17
+ * IO wait methods are built in ruby now, just for backward compatibility.
416
18
  */
417
19
 
418
20
  void
419
21
  Init_wait(void)
420
22
  {
421
- #ifdef HAVE_RB_EXT_RACTOR_SAFE
422
- RB_EXT_RACTOR_SAFE(true);
423
- #endif
424
-
425
- rb_define_method(rb_cIO, "nread", io_nread, 0);
426
- rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
427
-
428
- #ifndef RUBY_IO_WAIT_METHODS
429
- rb_define_method(rb_cIO, "wait", io_wait, -1);
430
-
431
- rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
432
- rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
433
- #ifdef HAVE_RB_IO_WAIT
434
- rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
435
- #endif
436
- #endif
437
23
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-wait
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nobu Nakada
8
8
  - Charles Oliver Nutter
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-11 00:00:00.000000000 Z
11
+ date: 2025-12-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Waits until IO is readable or writable without blocking.
14
14
  email:
@@ -41,7 +41,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
41
41
  requirements:
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: '3.0'
44
+ version: '3.2'
45
45
  required_rubygems_version: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="