nio4r 2.5.2 → 2.7.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/workflow.yml +61 -0
  3. data/.mailmap +16 -0
  4. data/.rubocop.yml +30 -11
  5. data/Gemfile +6 -6
  6. data/{CHANGES.md → changes.md} +78 -1
  7. data/examples/echo_server.rb +9 -2
  8. data/ext/libev/Changes +71 -2
  9. data/ext/libev/ev.c +611 -198
  10. data/ext/libev/ev.h +25 -22
  11. data/ext/libev/ev_epoll.c +16 -14
  12. data/ext/libev/ev_iouring.c +694 -0
  13. data/ext/libev/ev_kqueue.c +4 -4
  14. data/ext/libev/ev_linuxaio.c +78 -100
  15. data/ext/libev/ev_poll.c +6 -6
  16. data/ext/libev/ev_port.c +3 -3
  17. data/ext/libev/ev_select.c +6 -6
  18. data/ext/libev/ev_vars.h +34 -0
  19. data/ext/libev/ev_win32.c +2 -2
  20. data/ext/libev/ev_wrap.h +56 -0
  21. data/ext/nio4r/.clang-format +16 -0
  22. data/ext/nio4r/bytebuffer.c +101 -65
  23. data/ext/nio4r/extconf.rb +26 -0
  24. data/ext/nio4r/libev.h +1 -3
  25. data/ext/nio4r/monitor.c +81 -53
  26. data/ext/nio4r/nio4r.h +6 -15
  27. data/ext/nio4r/nio4r_ext.c +1 -1
  28. data/ext/nio4r/org/nio4r/ByteBuffer.java +2 -0
  29. data/ext/nio4r/org/nio4r/Monitor.java +1 -0
  30. data/ext/nio4r/org/nio4r/Selector.java +8 -10
  31. data/ext/nio4r/selector.c +132 -93
  32. data/lib/nio/bytebuffer.rb +10 -0
  33. data/lib/nio/monitor.rb +8 -1
  34. data/lib/nio/selector.rb +27 -10
  35. data/lib/nio/version.rb +6 -1
  36. data/lib/nio.rb +29 -1
  37. data/lib/nio4r.rb +5 -0
  38. data/license.md +77 -0
  39. data/nio4r.gemspec +6 -5
  40. data/rakelib/extension.rake +1 -2
  41. data/readme.md +91 -0
  42. data/spec/nio/acceptables_spec.rb +4 -0
  43. data/spec/nio/bytebuffer_spec.rb +6 -1
  44. data/spec/nio/monitor_spec.rb +7 -0
  45. data/spec/nio/selectables/pipe_spec.rb +6 -0
  46. data/spec/nio/selectables/ssl_socket_spec.rb +7 -0
  47. data/spec/nio/selectables/tcp_socket_spec.rb +7 -0
  48. data/spec/nio/selectables/udp_socket_spec.rb +9 -2
  49. data/spec/nio/selector_spec.rb +16 -1
  50. data/spec/spec_helper.rb +7 -2
  51. data/spec/support/selectable_examples.rb +8 -0
  52. metadata +20 -16
  53. data/.travis.yml +0 -44
  54. data/Guardfile +0 -10
  55. data/README.md +0 -150
  56. data/appveyor.yml +0 -40
data/ext/nio4r/selector.c CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  #include "nio4r.h"
7
7
  #ifdef HAVE_RUBYSIG_H
8
- # include "rubysig.h"
8
+ #include "rubysig.h"
9
9
  #endif
10
10
 
11
11
  #ifdef HAVE_UNISTD_H
@@ -14,18 +14,19 @@
14
14
  #include <io.h>
15
15
  #endif
16
16
 
17
- #include <fcntl.h>
18
17
  #include <assert.h>
18
+ #include <fcntl.h>
19
19
 
20
20
  static VALUE mNIO = Qnil;
21
- static VALUE cNIO_Monitor = Qnil;
21
+ static VALUE cNIO_Monitor = Qnil;
22
22
  static VALUE cNIO_Selector = Qnil;
23
23
 
24
24
  /* Allocator/deallocator */
25
25
  static VALUE NIO_Selector_allocate(VALUE klass);
26
- static void NIO_Selector_mark(struct NIO_Selector *loop);
26
+ static void NIO_Selector_mark(void *data);
27
27
  static void NIO_Selector_shutdown(struct NIO_Selector *selector);
28
- static void NIO_Selector_free(struct NIO_Selector *loop);
28
+ static void NIO_Selector_free(void *data);
29
+ static size_t NIO_Selector_memsize(const void *data);
29
30
 
30
31
  /* Class methods */
31
32
  static VALUE NIO_Selector_supported_backends(VALUE klass);
@@ -43,13 +44,13 @@ static VALUE NIO_Selector_closed(VALUE self);
43
44
  static VALUE NIO_Selector_is_empty(VALUE self);
44
45
 
45
46
  /* Internal functions */
46
- static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE *args), VALUE *args);
47
+ static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE arg), VALUE arg);
47
48
  static VALUE NIO_Selector_unlock(VALUE lock);
48
- static VALUE NIO_Selector_register_synchronized(VALUE *args);
49
- static VALUE NIO_Selector_deregister_synchronized(VALUE *args);
50
- static VALUE NIO_Selector_select_synchronized(VALUE *args);
51
- static VALUE NIO_Selector_close_synchronized(VALUE *args);
52
- static VALUE NIO_Selector_closed_synchronized(VALUE *args);
49
+ static VALUE NIO_Selector_register_synchronized(VALUE arg);
50
+ static VALUE NIO_Selector_deregister_synchronized(VALUE arg);
51
+ static VALUE NIO_Selector_select_synchronized(VALUE arg);
52
+ static VALUE NIO_Selector_close_synchronized(VALUE arg);
53
+ static VALUE NIO_Selector_closed_synchronized(VALUE arg);
53
54
 
54
55
  static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout);
55
56
  static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
@@ -62,7 +63,7 @@ static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *
62
63
  #define BUSYWAIT_INTERVAL 0.01
63
64
 
64
65
  /* Selectors wait for events */
65
- void Init_NIO_Selector()
66
+ void Init_NIO_Selector(void)
66
67
  {
67
68
  mNIO = rb_define_module("NIO");
68
69
  cNIO_Selector = rb_define_class_under(mNIO, "Selector", rb_cObject);
@@ -80,9 +81,21 @@ void Init_NIO_Selector()
80
81
  rb_define_method(cNIO_Selector, "closed?", NIO_Selector_closed, 0);
81
82
  rb_define_method(cNIO_Selector, "empty?", NIO_Selector_is_empty, 0);
82
83
 
83
- cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
84
+ cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
84
85
  }
85
86
 
87
+ static const rb_data_type_t NIO_Selector_type = {
88
+ "NIO::Selector",
89
+ {
90
+ NIO_Selector_mark,
91
+ NIO_Selector_free,
92
+ NIO_Selector_memsize,
93
+ },
94
+ 0,
95
+ 0,
96
+ RUBY_TYPED_WB_PROTECTED // Don't free immediately because of shutdown
97
+ };
98
+
86
99
  /* Create the libev event loop and incoming event buffer */
87
100
  static VALUE NIO_Selector_allocate(VALUE klass)
88
101
  {
@@ -95,18 +108,16 @@ static VALUE NIO_Selector_allocate(VALUE klass)
95
108
  safety. Pipes are nice and safe to use between threads.
96
109
 
97
110
  Note that Java NIO uses this same mechanism */
98
- if(pipe(fds) < 0) {
111
+ if (pipe(fds) < 0) {
99
112
  rb_sys_fail("pipe");
100
113
  }
101
114
 
102
115
  /* Use non-blocking reads/writes during wakeup, in case the buffer is full */
103
- if(fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0 ||
104
- fcntl(fds[1], F_SETFL, O_NONBLOCK) < 0) {
116
+ if (fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0 || fcntl(fds[1], F_SETFL, O_NONBLOCK) < 0) {
105
117
  rb_sys_fail("fcntl");
106
118
  }
107
119
 
108
- selector = (struct NIO_Selector *)xmalloc(sizeof(struct NIO_Selector));
109
-
120
+ VALUE obj = TypedData_Make_Struct(klass, struct NIO_Selector, &NIO_Selector_type, selector);
110
121
  /* Defer initializing the loop to #initialize */
111
122
  selector->ev_loop = 0;
112
123
 
@@ -119,15 +130,22 @@ static VALUE NIO_Selector_allocate(VALUE klass)
119
130
  selector->wakeup.data = (void *)selector;
120
131
 
121
132
  selector->closed = selector->selecting = selector->wakeup_fired = selector->ready_count = 0;
122
- selector->ready_array = Qnil;
133
+ RB_OBJ_WRITE(obj, &selector->ready_array, Qnil);
134
+ return obj;
135
+ }
123
136
 
124
- return Data_Wrap_Struct(klass, NIO_Selector_mark, NIO_Selector_free, selector);
137
+ struct NIO_Selector *NIO_Selector_unwrap(VALUE self)
138
+ {
139
+ struct NIO_Selector *selector;
140
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
141
+ return selector;
125
142
  }
126
143
 
127
144
  /* NIO selectors store all Ruby objects in instance variables so mark is a stub */
128
- static void NIO_Selector_mark(struct NIO_Selector *selector)
145
+ static void NIO_Selector_mark(void *data)
129
146
  {
130
- if(selector->ready_array != Qnil) {
147
+ struct NIO_Selector *selector = (struct NIO_Selector *)data;
148
+ if (selector->ready_array != Qnil) {
131
149
  rb_gc_mark(selector->ready_array);
132
150
  }
133
151
  }
@@ -136,14 +154,14 @@ static void NIO_Selector_mark(struct NIO_Selector *selector)
136
154
  Called by both NIO::Selector#close and the finalizer below */
137
155
  static void NIO_Selector_shutdown(struct NIO_Selector *selector)
138
156
  {
139
- if(selector->closed) {
157
+ if (selector->closed) {
140
158
  return;
141
159
  }
142
160
 
143
161
  close(selector->wakeup_reader);
144
162
  close(selector->wakeup_writer);
145
163
 
146
- if(selector->ev_loop) {
164
+ if (selector->ev_loop) {
147
165
  ev_loop_destroy(selector->ev_loop);
148
166
  selector->ev_loop = 0;
149
167
  }
@@ -152,37 +170,52 @@ static void NIO_Selector_shutdown(struct NIO_Selector *selector)
152
170
  }
153
171
 
154
172
  /* Ruby finalizer for selector objects */
155
- static void NIO_Selector_free(struct NIO_Selector *selector)
173
+ static void NIO_Selector_free(void *data)
156
174
  {
175
+ struct NIO_Selector *selector = (struct NIO_Selector *)data;
157
176
  NIO_Selector_shutdown(selector);
158
177
  xfree(selector);
159
178
  }
160
179
 
180
+ static size_t NIO_Selector_memsize(const void *data)
181
+ {
182
+ return sizeof(struct NIO_Selector);
183
+ }
184
+
161
185
  /* Return an array of symbols for supported backends */
162
- static VALUE NIO_Selector_supported_backends(VALUE klass) {
186
+ static VALUE NIO_Selector_supported_backends(VALUE klass)
187
+ {
163
188
  unsigned int backends = ev_supported_backends();
164
189
  VALUE result = rb_ary_new();
165
190
 
166
- if(backends & EVBACKEND_EPOLL) {
191
+ if (backends & EVBACKEND_EPOLL) {
167
192
  rb_ary_push(result, ID2SYM(rb_intern("epoll")));
168
193
  }
169
194
 
170
- if(backends & EVBACKEND_POLL) {
195
+ if (backends & EVBACKEND_POLL) {
171
196
  rb_ary_push(result, ID2SYM(rb_intern("poll")));
172
197
  }
173
198
 
174
- if(backends & EVBACKEND_KQUEUE) {
199
+ if (backends & EVBACKEND_KQUEUE) {
175
200
  rb_ary_push(result, ID2SYM(rb_intern("kqueue")));
176
201
  }
177
202
 
178
- if(backends & EVBACKEND_SELECT) {
203
+ if (backends & EVBACKEND_SELECT) {
179
204
  rb_ary_push(result, ID2SYM(rb_intern("select")));
180
205
  }
181
206
 
182
- if(backends & EVBACKEND_PORT) {
207
+ if (backends & EVBACKEND_PORT) {
183
208
  rb_ary_push(result, ID2SYM(rb_intern("port")));
184
209
  }
185
210
 
211
+ if (backends & EVBACKEND_LINUXAIO) {
212
+ rb_ary_push(result, ID2SYM(rb_intern("linuxaio")));
213
+ }
214
+
215
+ if (backends & EVBACKEND_IOURING) {
216
+ rb_ary_push(result, ID2SYM(rb_intern("io_uring")));
217
+ }
218
+
186
219
  return result;
187
220
  }
188
221
 
@@ -197,31 +230,33 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
197
230
  struct NIO_Selector *selector;
198
231
  unsigned int flags = 0;
199
232
 
200
- Data_Get_Struct(self, struct NIO_Selector, selector);
233
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
201
234
 
202
235
  rb_scan_args(argc, argv, "01", &backend);
203
236
 
204
- if(backend != Qnil) {
205
- if(!rb_ary_includes(NIO_Selector_supported_backends(CLASS_OF(self)), backend)) {
206
- rb_raise(rb_eArgError, "unsupported backend: %s",
207
- RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
237
+ if (backend != Qnil) {
238
+ if (!rb_ary_includes(NIO_Selector_supported_backends(CLASS_OF(self)), backend)) {
239
+ rb_raise(rb_eArgError, "unsupported backend: %s", RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
208
240
  }
209
241
 
210
242
  backend_id = SYM2ID(backend);
211
243
 
212
- if(backend_id == rb_intern("epoll")) {
244
+ if (backend_id == rb_intern("epoll")) {
213
245
  flags = EVBACKEND_EPOLL;
214
- } else if(backend_id == rb_intern("poll")) {
246
+ } else if (backend_id == rb_intern("poll")) {
215
247
  flags = EVBACKEND_POLL;
216
- } else if(backend_id == rb_intern("kqueue")) {
248
+ } else if (backend_id == rb_intern("kqueue")) {
217
249
  flags = EVBACKEND_KQUEUE;
218
- } else if(backend_id == rb_intern("select")) {
250
+ } else if (backend_id == rb_intern("select")) {
219
251
  flags = EVBACKEND_SELECT;
220
- } else if(backend_id == rb_intern("port")) {
252
+ } else if (backend_id == rb_intern("port")) {
221
253
  flags = EVBACKEND_PORT;
254
+ } else if (backend_id == rb_intern("linuxaio")) {
255
+ flags = EVBACKEND_LINUXAIO;
256
+ } else if (backend_id == rb_intern("io_uring")) {
257
+ flags = EVBACKEND_IOURING;
222
258
  } else {
223
- rb_raise(rb_eArgError, "unsupported backend: %s",
224
- RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
259
+ rb_raise(rb_eArgError, "unsupported backend: %s", RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
225
260
  }
226
261
  }
227
262
 
@@ -229,7 +264,7 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
229
264
  assert(!selector->ev_loop);
230
265
 
231
266
  selector->ev_loop = ev_loop_new(flags);
232
- if(!selector->ev_loop) {
267
+ if (!selector->ev_loop) {
233
268
  rb_raise(rb_eIOError, "error initializing event loop");
234
269
  }
235
270
 
@@ -245,11 +280,12 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
245
280
  return Qnil;
246
281
  }
247
282
 
248
- static VALUE NIO_Selector_backend(VALUE self) {
283
+ static VALUE NIO_Selector_backend(VALUE self)
284
+ {
249
285
  struct NIO_Selector *selector;
250
286
 
251
- Data_Get_Struct(self, struct NIO_Selector, selector);
252
- if(selector->closed) {
287
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
288
+ if (selector->closed) {
253
289
  rb_raise(rb_eIOError, "selector is closed");
254
290
  }
255
291
 
@@ -264,29 +300,33 @@ static VALUE NIO_Selector_backend(VALUE self) {
264
300
  return ID2SYM(rb_intern("select"));
265
301
  case EVBACKEND_PORT:
266
302
  return ID2SYM(rb_intern("port"));
303
+ case EVBACKEND_LINUXAIO:
304
+ return ID2SYM(rb_intern("linuxaio"));
305
+ case EVBACKEND_IOURING:
306
+ return ID2SYM(rb_intern("io_uring"));
267
307
  }
268
308
 
269
309
  return ID2SYM(rb_intern("unknown"));
270
310
  }
271
311
 
272
312
  /* Synchronize around a reentrant selector lock */
273
- static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE *args), VALUE *args)
313
+ static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE arg), VALUE arg)
274
314
  {
275
315
  VALUE current_thread, lock_holder, lock;
276
316
 
277
317
  current_thread = rb_thread_current();
278
318
  lock_holder = rb_ivar_get(self, rb_intern("lock_holder"));
279
319
 
280
- if(lock_holder != current_thread) {
320
+ if (lock_holder != current_thread) {
281
321
  lock = rb_ivar_get(self, rb_intern("lock"));
282
322
  rb_funcall(lock, rb_intern("lock"), 0);
283
323
  rb_ivar_set(self, rb_intern("lock_holder"), current_thread);
284
324
 
285
325
  /* We've acquired the lock, so ensure we unlock it */
286
- return rb_ensure(func, (VALUE)args, NIO_Selector_unlock, self);
326
+ return rb_ensure(func, (VALUE)arg, NIO_Selector_unlock, self);
287
327
  } else {
288
328
  /* We already hold the selector lock, so no need to unlock it */
289
- return func(args);
329
+ return func(arg);
290
330
  }
291
331
  }
292
332
 
@@ -307,29 +347,30 @@ static VALUE NIO_Selector_unlock(VALUE self)
307
347
  static VALUE NIO_Selector_register(VALUE self, VALUE io, VALUE interests)
308
348
  {
309
349
  VALUE args[3] = {self, io, interests};
310
- return NIO_Selector_synchronize(self, NIO_Selector_register_synchronized, args);
350
+ return NIO_Selector_synchronize(self, NIO_Selector_register_synchronized, (VALUE)args);
311
351
  }
312
352
 
313
353
  /* Internal implementation of register after acquiring mutex */
314
- static VALUE NIO_Selector_register_synchronized(VALUE *args)
354
+ static VALUE NIO_Selector_register_synchronized(VALUE _args)
315
355
  {
316
356
  VALUE self, io, interests, selectables, monitor;
317
357
  VALUE monitor_args[3];
318
358
  struct NIO_Selector *selector;
319
359
 
360
+ VALUE *args = (VALUE *)_args;
320
361
  self = args[0];
321
362
  io = args[1];
322
363
  interests = args[2];
323
364
 
324
- Data_Get_Struct(self, struct NIO_Selector, selector);
325
- if(selector->closed) {
365
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
366
+ if (selector->closed) {
326
367
  rb_raise(rb_eIOError, "selector is closed");
327
368
  }
328
369
 
329
370
  selectables = rb_ivar_get(self, rb_intern("selectables"));
330
371
  monitor = rb_hash_lookup(selectables, io);
331
372
 
332
- if(monitor != Qnil)
373
+ if (monitor != Qnil)
333
374
  rb_raise(rb_eArgError, "this IO is already registered with selector");
334
375
 
335
376
  /* Create a new NIO::Monitor */
@@ -347,21 +388,22 @@ static VALUE NIO_Selector_register_synchronized(VALUE *args)
347
388
  static VALUE NIO_Selector_deregister(VALUE self, VALUE io)
348
389
  {
349
390
  VALUE args[2] = {self, io};
350
- return NIO_Selector_synchronize(self, NIO_Selector_deregister_synchronized, args);
391
+ return NIO_Selector_synchronize(self, NIO_Selector_deregister_synchronized, (VALUE)args);
351
392
  }
352
393
 
353
394
  /* Internal implementation of register after acquiring mutex */
354
- static VALUE NIO_Selector_deregister_synchronized(VALUE *args)
395
+ static VALUE NIO_Selector_deregister_synchronized(VALUE _args)
355
396
  {
356
397
  VALUE self, io, selectables, monitor;
357
398
 
399
+ VALUE *args = (VALUE *)_args;
358
400
  self = args[0];
359
401
  io = args[1];
360
402
 
361
403
  selectables = rb_ivar_get(self, rb_intern("selectables"));
362
404
  monitor = rb_hash_delete(selectables, io);
363
405
 
364
- if(monitor != Qnil) {
406
+ if (monitor != Qnil) {
365
407
  rb_funcall(monitor, rb_intern("close"), 1, Qfalse);
366
408
  }
367
409
 
@@ -381,53 +423,52 @@ static VALUE NIO_Selector_is_registered(VALUE self, VALUE io)
381
423
  static VALUE NIO_Selector_select(int argc, VALUE *argv, VALUE self)
382
424
  {
383
425
  VALUE timeout;
384
- VALUE args[2];
385
426
 
386
427
  rb_scan_args(argc, argv, "01", &timeout);
387
428
 
388
- if(timeout != Qnil && NUM2DBL(timeout) < 0) {
429
+ if (timeout != Qnil && NUM2DBL(timeout) < 0) {
389
430
  rb_raise(rb_eArgError, "time interval must be positive");
390
431
  }
391
432
 
392
- args[0] = self;
393
- args[1] = timeout;
394
-
395
- return NIO_Selector_synchronize(self, NIO_Selector_select_synchronized, args);
433
+ VALUE args[2] = {self, timeout};
434
+ return NIO_Selector_synchronize(self, NIO_Selector_select_synchronized, (VALUE)args);
396
435
  }
397
436
 
398
437
  /* Internal implementation of select with the selector lock held */
399
- static VALUE NIO_Selector_select_synchronized(VALUE *args)
438
+ static VALUE NIO_Selector_select_synchronized(VALUE _args)
400
439
  {
401
440
  int ready;
402
441
  VALUE ready_array;
403
442
  struct NIO_Selector *selector;
404
443
 
405
- Data_Get_Struct(args[0], struct NIO_Selector, selector);
444
+ VALUE *args = (VALUE *)_args;
445
+
446
+ TypedData_Get_Struct(args[0], struct NIO_Selector, &NIO_Selector_type, selector);
406
447
 
407
- if(selector->closed) {
448
+ if (selector->closed) {
408
449
  rb_raise(rb_eIOError, "selector is closed");
409
450
  }
410
451
 
411
- if(!rb_block_given_p()) {
412
- selector->ready_array = rb_ary_new();
452
+ if (!rb_block_given_p()) {
453
+ RB_OBJ_WRITE(args[0], &selector->ready_array, rb_ary_new());
413
454
  }
414
455
 
415
456
  ready = NIO_Selector_run(selector, args[1]);
416
457
 
417
458
  /* Timeout */
418
- if(ready < 0) {
419
- if(!rb_block_given_p()) {
420
- selector->ready_array = Qnil;
459
+ if (ready < 0) {
460
+ if (!rb_block_given_p()) {
461
+ RB_OBJ_WRITE(args[0], &selector->ready_array, Qnil);
421
462
  }
422
463
 
423
464
  return Qnil;
424
465
  }
425
466
 
426
- if(rb_block_given_p()) {
467
+ if (rb_block_given_p()) {
427
468
  return INT2NUM(ready);
428
469
  } else {
429
470
  ready_array = selector->ready_array;
430
- selector->ready_array = Qnil;
471
+ RB_OBJ_WRITE(args[0], &selector->ready_array, Qnil);
431
472
  return ready_array;
432
473
  }
433
474
  }
@@ -441,12 +482,12 @@ static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
441
482
  selector->selecting = 1;
442
483
  selector->wakeup_fired = 0;
443
484
 
444
- if(timeout == Qnil) {
485
+ if (timeout == Qnil) {
445
486
  /* Don't fire a wakeup timeout if we weren't passed one */
446
487
  ev_timer_stop(selector->ev_loop, &selector->timer);
447
488
  } else {
448
489
  timeout_val = NUM2DBL(timeout);
449
- if(timeout_val == 0) {
490
+ if (timeout_val == 0) {
450
491
  /* If we've been given an explicit timeout of 0, perform a non-blocking
451
492
  select operation */
452
493
  ev_run_flags = EVRUN_NOWAIT;
@@ -462,7 +503,7 @@ static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
462
503
  result = selector->ready_count;
463
504
  selector->selecting = selector->ready_count = 0;
464
505
 
465
- if(result > 0 || selector->wakeup_fired) {
506
+ if (result > 0 || selector->wakeup_fired) {
466
507
  selector->wakeup_fired = 0;
467
508
  return result;
468
509
  } else {
@@ -474,9 +515,9 @@ static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
474
515
  static VALUE NIO_Selector_wakeup(VALUE self)
475
516
  {
476
517
  struct NIO_Selector *selector;
477
- Data_Get_Struct(self, struct NIO_Selector, selector);
518
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
478
519
 
479
- if(selector->closed) {
520
+ if (selector->closed) {
480
521
  rb_raise(rb_eIOError, "selector is closed");
481
522
  }
482
523
 
@@ -489,15 +530,14 @@ static VALUE NIO_Selector_wakeup(VALUE self)
489
530
  /* Close the selector and free system resources */
490
531
  static VALUE NIO_Selector_close(VALUE self)
491
532
  {
492
- VALUE args[1] = {self};
493
- return NIO_Selector_synchronize(self, NIO_Selector_close_synchronized, args);
533
+ return NIO_Selector_synchronize(self, NIO_Selector_close_synchronized, self);
494
534
  }
495
535
 
496
- static VALUE NIO_Selector_close_synchronized(VALUE *args)
536
+ static VALUE NIO_Selector_close_synchronized(VALUE self)
497
537
  {
498
538
  struct NIO_Selector *selector;
499
- VALUE self = args[0];
500
- Data_Get_Struct(self, struct NIO_Selector, selector);
539
+
540
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
501
541
 
502
542
  NIO_Selector_shutdown(selector);
503
543
 
@@ -507,15 +547,14 @@ static VALUE NIO_Selector_close_synchronized(VALUE *args)
507
547
  /* Is the selector closed? */
508
548
  static VALUE NIO_Selector_closed(VALUE self)
509
549
  {
510
- VALUE args[1] = {self};
511
- return NIO_Selector_synchronize(self, NIO_Selector_closed_synchronized, args);
550
+ return NIO_Selector_synchronize(self, NIO_Selector_closed_synchronized, self);
512
551
  }
513
552
 
514
- static VALUE NIO_Selector_closed_synchronized(VALUE *args)
553
+ static VALUE NIO_Selector_closed_synchronized(VALUE self)
515
554
  {
516
555
  struct NIO_Selector *selector;
517
- VALUE self = args[0];
518
- Data_Get_Struct(self, struct NIO_Selector, selector);
556
+
557
+ TypedData_Get_Struct(self, struct NIO_Selector, &NIO_Selector_type, selector);
519
558
 
520
559
  return selector->closed ? Qtrue : Qfalse;
521
560
  }
@@ -528,7 +567,6 @@ static VALUE NIO_Selector_is_empty(VALUE self)
528
567
  return rb_funcall(selectables, rb_intern("empty?"), 0) == Qtrue ? Qtrue : Qfalse;
529
568
  }
530
569
 
531
-
532
570
  /* Called whenever a timeout fires on the event loop */
533
571
  static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents)
534
572
  {
@@ -542,7 +580,8 @@ static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *
542
580
  selector->selecting = 0;
543
581
 
544
582
  /* Drain the wakeup pipe, giving us level-triggered behavior */
545
- while(read(selector->wakeup_reader, buffer, 128) > 0);
583
+ while (read(selector->wakeup_reader, buffer, 128) > 0)
584
+ ;
546
585
  }
547
586
 
548
587
  /* libev callback fired whenever a monitor gets an event */
@@ -558,7 +597,7 @@ void NIO_Selector_monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, in
558
597
  selector->ready_count++;
559
598
  monitor_data->revents = revents;
560
599
 
561
- if(rb_block_given_p()) {
600
+ if (rb_block_given_p()) {
562
601
  rb_yield(monitor);
563
602
  } else {
564
603
  assert(selector->ready_array != Qnil);
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2016, by Upekshe Jayasekera.
5
+ # Copyright, 2016-2017, by Tony Arcieri.
6
+ # Copyright, 2020, by Thomas Dziedzic.
7
+ # Copyright, 2023, by Samuel Williams.
8
+
3
9
  module NIO
4
10
  # Efficient byte buffers for performant I/O operations
5
11
  class ByteBuffer
@@ -24,6 +30,7 @@ module NIO
24
30
  # @return [NIO::ByteBuffer]
25
31
  def initialize(capacity)
26
32
  raise TypeError, "no implicit conversion of #{capacity.class} to Integer" unless capacity.is_a?(Integer)
33
+
27
34
  @capacity = capacity
28
35
  clear
29
36
  end
@@ -119,9 +126,11 @@ module NIO
119
126
  # @return [self]
120
127
  def put(str)
121
128
  raise TypeError, "expected String, got #{str.class}" unless str.respond_to?(:to_str)
129
+
122
130
  str = str.to_str
123
131
 
124
132
  raise OverflowError, "buffer is full" if str.length > @limit - @position
133
+
125
134
  @buffer[@position...str.length] = str
126
135
  @position += str.length
127
136
  self
@@ -188,6 +197,7 @@ module NIO
188
197
  # @raise [NIO::ByteBuffer::MarkUnsetError] mark has not been set (call `#mark` first)
189
198
  def reset
190
199
  raise MarkUnsetError, "mark has not been set" unless @mark
200
+
191
201
  @position = @mark
192
202
  self
193
203
  end
data/lib/nio/monitor.rb CHANGED
@@ -1,5 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2018, by Tony Arcieri.
5
+ # Copyright, 2015, by Upekshe Jayasekera.
6
+ # Copyright, 2015, by Vladimir Kochnev.
7
+ # Copyright, 2018-2023, by Samuel Williams.
8
+ # Copyright, 2019-2020, by Gregory Longtin.
9
+
3
10
  module NIO
4
11
  # Monitors watch IO objects for specific events
5
12
  class Monitor
@@ -8,7 +15,7 @@ module NIO
8
15
 
9
16
  # :nodoc:
10
17
  def initialize(io, interests, selector)
11
- unless io.is_a? OpenSSL::SSL::SSLSocket
18
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
12
19
  unless io.is_a?(IO)
13
20
  if IO.respond_to? :try_convert
14
21
  io = IO.try_convert(io)
data/lib/nio/selector.rb CHANGED
@@ -1,5 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2017, by Tony Arcieri.
5
+ # Copyright, 2012, by Logan Bowers.
6
+ # Copyright, 2013, by Sadayuki Furuhashi.
7
+ # Copyright, 2013, by Stephen von Takach.
8
+ # Copyright, 2013, by Tim Carey-Smith.
9
+ # Copyright, 2013, by Ravil Bayramgalin.
10
+ # Copyright, 2014, by Sergey Avseyev.
11
+ # Copyright, 2014, by John Thornton.
12
+ # Copyright, 2015, by Vladimir Kochnev.
13
+ # Copyright, 2015, by Upekshe Jayasekera.
14
+ # Copyright, 2019-2020, by Gregory Longtin.
15
+ # Copyright, 2020-2021, by Joao Fernandes.
16
+ # Copyright, 2023, by Samuel Williams.
17
+
3
18
  require "set"
4
19
 
5
20
  module NIO
@@ -14,7 +29,7 @@ module NIO
14
29
 
15
30
  # Create a new NIO::Selector
16
31
  def initialize(backend = :ruby)
17
- raise ArgumentError, "unsupported backend: #{backend}" unless backend == :ruby
32
+ raise ArgumentError, "unsupported backend: #{backend}" unless [:ruby, nil].include?(backend)
18
33
 
19
34
  @selectables = {}
20
35
  @lock = Mutex.new
@@ -26,14 +41,16 @@ module NIO
26
41
 
27
42
  # Return a symbol representing the backend I/O multiplexing mechanism used.
28
43
  # Supported backends are:
29
- # * :ruby - pure Ruby (i.e IO.select)
30
- # * :java - Java NIO on JRuby
31
- # * :epoll - libev w\ Linux epoll
32
- # * :poll - libev w\ POSIX poll
33
- # * :kqueue - libev w\ BSD kqueue
34
- # * :select - libev w\ SysV select
35
- # * :port - libev w\ I/O completion ports
36
- # * :unknown - libev w\ unknown backend
44
+ # * :ruby - pure Ruby (i.e IO.select)
45
+ # * :java - Java NIO on JRuby
46
+ # * :epoll - libev w\ Linux epoll
47
+ # * :poll - libev w\ POSIX poll
48
+ # * :kqueue - libev w\ BSD kqueue
49
+ # * :select - libev w\ SysV select
50
+ # * :port - libev w\ I/O completion ports
51
+ # * :linuxaio - libev w\ Linux AIO io_submit (experimental)
52
+ # * :io_uring - libev w\ Linux io_uring (experimental)
53
+ # * :unknown - libev w\ unknown backend
37
54
  def backend
38
55
  :ruby
39
56
  end
@@ -44,7 +61,7 @@ module NIO
44
61
  # * :w - is the IO writeable?
45
62
  # * :rw - is the IO either readable or writeable?
46
63
  def register(io, interest)
47
- unless io.is_a? OpenSSL::SSL::SSLSocket
64
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
48
65
  io = IO.try_convert(io)
49
66
  end
50
67
 
data/lib/nio/version.rb CHANGED
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2018, by Tony Arcieri.
5
+ # Copyright, 2018-2023, by Samuel Williams.
6
+ # Copyright, 2023, by Tsimnuj Hawj.
7
+
3
8
  module NIO
4
- VERSION = "2.5.2"
9
+ VERSION = "2.7.0"
5
10
  end