nio4r 2.5.2 → 2.7.0

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