nio4r 2.5.2 → 2.5.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/workflow.yml +61 -0
  3. data/.rubocop.yml +30 -11
  4. data/CHANGES.md +60 -1
  5. data/Gemfile +2 -4
  6. data/README.md +7 -58
  7. data/examples/echo_server.rb +2 -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 +27 -28
  23. data/ext/nio4r/extconf.rb +11 -0
  24. data/ext/nio4r/libev.h +1 -3
  25. data/ext/nio4r/monitor.c +34 -31
  26. data/ext/nio4r/nio4r.h +7 -12
  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 +89 -75
  32. data/lib/nio/bytebuffer.rb +4 -0
  33. data/lib/nio/monitor.rb +1 -1
  34. data/lib/nio/selector.rb +12 -10
  35. data/lib/nio/version.rb +1 -1
  36. data/lib/nio.rb +20 -1
  37. data/license.md +66 -0
  38. data/nio4r.gemspec +2 -2
  39. data/rakelib/extension.rake +1 -2
  40. data/spec/nio/bytebuffer_spec.rb +0 -1
  41. data/spec/nio/selectables/udp_socket_spec.rb +2 -2
  42. data/spec/nio/selector_spec.rb +4 -1
  43. data/spec/spec_helper.rb +2 -3
  44. metadata +13 -12
  45. data/.travis.yml +0 -44
  46. data/Guardfile +0 -10
  47. 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,11 +14,11 @@
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 */
@@ -43,13 +43,13 @@ static VALUE NIO_Selector_closed(VALUE self);
43
43
  static VALUE NIO_Selector_is_empty(VALUE self);
44
44
 
45
45
  /* Internal functions */
46
- static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE *args), VALUE *args);
46
+ static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE arg), VALUE arg);
47
47
  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);
48
+ static VALUE NIO_Selector_register_synchronized(VALUE arg);
49
+ static VALUE NIO_Selector_deregister_synchronized(VALUE arg);
50
+ static VALUE NIO_Selector_select_synchronized(VALUE arg);
51
+ static VALUE NIO_Selector_close_synchronized(VALUE arg);
52
+ static VALUE NIO_Selector_closed_synchronized(VALUE arg);
53
53
 
54
54
  static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout);
55
55
  static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
@@ -62,7 +62,7 @@ static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *
62
62
  #define BUSYWAIT_INTERVAL 0.01
63
63
 
64
64
  /* Selectors wait for events */
65
- void Init_NIO_Selector()
65
+ void Init_NIO_Selector(void)
66
66
  {
67
67
  mNIO = rb_define_module("NIO");
68
68
  cNIO_Selector = rb_define_class_under(mNIO, "Selector", rb_cObject);
@@ -80,7 +80,7 @@ void Init_NIO_Selector()
80
80
  rb_define_method(cNIO_Selector, "closed?", NIO_Selector_closed, 0);
81
81
  rb_define_method(cNIO_Selector, "empty?", NIO_Selector_is_empty, 0);
82
82
 
83
- cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
83
+ cNIO_Monitor = rb_define_class_under(mNIO, "Monitor", rb_cObject);
84
84
  }
85
85
 
86
86
  /* Create the libev event loop and incoming event buffer */
@@ -95,13 +95,12 @@ static VALUE NIO_Selector_allocate(VALUE klass)
95
95
  safety. Pipes are nice and safe to use between threads.
96
96
 
97
97
  Note that Java NIO uses this same mechanism */
98
- if(pipe(fds) < 0) {
98
+ if (pipe(fds) < 0) {
99
99
  rb_sys_fail("pipe");
100
100
  }
101
101
 
102
102
  /* 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) {
103
+ if (fcntl(fds[0], F_SETFL, O_NONBLOCK) < 0 || fcntl(fds[1], F_SETFL, O_NONBLOCK) < 0) {
105
104
  rb_sys_fail("fcntl");
106
105
  }
107
106
 
@@ -127,7 +126,7 @@ static VALUE NIO_Selector_allocate(VALUE klass)
127
126
  /* NIO selectors store all Ruby objects in instance variables so mark is a stub */
128
127
  static void NIO_Selector_mark(struct NIO_Selector *selector)
129
128
  {
130
- if(selector->ready_array != Qnil) {
129
+ if (selector->ready_array != Qnil) {
131
130
  rb_gc_mark(selector->ready_array);
132
131
  }
133
132
  }
@@ -136,14 +135,14 @@ static void NIO_Selector_mark(struct NIO_Selector *selector)
136
135
  Called by both NIO::Selector#close and the finalizer below */
137
136
  static void NIO_Selector_shutdown(struct NIO_Selector *selector)
138
137
  {
139
- if(selector->closed) {
138
+ if (selector->closed) {
140
139
  return;
141
140
  }
142
141
 
143
142
  close(selector->wakeup_reader);
144
143
  close(selector->wakeup_writer);
145
144
 
146
- if(selector->ev_loop) {
145
+ if (selector->ev_loop) {
147
146
  ev_loop_destroy(selector->ev_loop);
148
147
  selector->ev_loop = 0;
149
148
  }
@@ -159,30 +158,39 @@ static void NIO_Selector_free(struct NIO_Selector *selector)
159
158
  }
160
159
 
161
160
  /* Return an array of symbols for supported backends */
162
- static VALUE NIO_Selector_supported_backends(VALUE klass) {
161
+ static VALUE NIO_Selector_supported_backends(VALUE klass)
162
+ {
163
163
  unsigned int backends = ev_supported_backends();
164
164
  VALUE result = rb_ary_new();
165
165
 
166
- if(backends & EVBACKEND_EPOLL) {
166
+ if (backends & EVBACKEND_EPOLL) {
167
167
  rb_ary_push(result, ID2SYM(rb_intern("epoll")));
168
168
  }
169
169
 
170
- if(backends & EVBACKEND_POLL) {
170
+ if (backends & EVBACKEND_POLL) {
171
171
  rb_ary_push(result, ID2SYM(rb_intern("poll")));
172
172
  }
173
173
 
174
- if(backends & EVBACKEND_KQUEUE) {
174
+ if (backends & EVBACKEND_KQUEUE) {
175
175
  rb_ary_push(result, ID2SYM(rb_intern("kqueue")));
176
176
  }
177
177
 
178
- if(backends & EVBACKEND_SELECT) {
178
+ if (backends & EVBACKEND_SELECT) {
179
179
  rb_ary_push(result, ID2SYM(rb_intern("select")));
180
180
  }
181
181
 
182
- if(backends & EVBACKEND_PORT) {
182
+ if (backends & EVBACKEND_PORT) {
183
183
  rb_ary_push(result, ID2SYM(rb_intern("port")));
184
184
  }
185
185
 
186
+ if (backends & EVBACKEND_LINUXAIO) {
187
+ rb_ary_push(result, ID2SYM(rb_intern("linuxaio")));
188
+ }
189
+
190
+ if (backends & EVBACKEND_IOURING) {
191
+ rb_ary_push(result, ID2SYM(rb_intern("io_uring")));
192
+ }
193
+
186
194
  return result;
187
195
  }
188
196
 
@@ -201,27 +209,29 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
201
209
 
202
210
  rb_scan_args(argc, argv, "01", &backend);
203
211
 
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)));
212
+ if (backend != Qnil) {
213
+ if (!rb_ary_includes(NIO_Selector_supported_backends(CLASS_OF(self)), backend)) {
214
+ rb_raise(rb_eArgError, "unsupported backend: %s", RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
208
215
  }
209
216
 
210
217
  backend_id = SYM2ID(backend);
211
218
 
212
- if(backend_id == rb_intern("epoll")) {
219
+ if (backend_id == rb_intern("epoll")) {
213
220
  flags = EVBACKEND_EPOLL;
214
- } else if(backend_id == rb_intern("poll")) {
221
+ } else if (backend_id == rb_intern("poll")) {
215
222
  flags = EVBACKEND_POLL;
216
- } else if(backend_id == rb_intern("kqueue")) {
223
+ } else if (backend_id == rb_intern("kqueue")) {
217
224
  flags = EVBACKEND_KQUEUE;
218
- } else if(backend_id == rb_intern("select")) {
225
+ } else if (backend_id == rb_intern("select")) {
219
226
  flags = EVBACKEND_SELECT;
220
- } else if(backend_id == rb_intern("port")) {
227
+ } else if (backend_id == rb_intern("port")) {
221
228
  flags = EVBACKEND_PORT;
229
+ } else if (backend_id == rb_intern("linuxaio")) {
230
+ flags = EVBACKEND_LINUXAIO;
231
+ } else if (backend_id == rb_intern("io_uring")) {
232
+ flags = EVBACKEND_IOURING;
222
233
  } else {
223
- rb_raise(rb_eArgError, "unsupported backend: %s",
224
- RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
234
+ rb_raise(rb_eArgError, "unsupported backend: %s", RSTRING_PTR(rb_funcall(backend, rb_intern("inspect"), 0)));
225
235
  }
226
236
  }
227
237
 
@@ -229,7 +239,7 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
229
239
  assert(!selector->ev_loop);
230
240
 
231
241
  selector->ev_loop = ev_loop_new(flags);
232
- if(!selector->ev_loop) {
242
+ if (!selector->ev_loop) {
233
243
  rb_raise(rb_eIOError, "error initializing event loop");
234
244
  }
235
245
 
@@ -245,11 +255,12 @@ static VALUE NIO_Selector_initialize(int argc, VALUE *argv, VALUE self)
245
255
  return Qnil;
246
256
  }
247
257
 
248
- static VALUE NIO_Selector_backend(VALUE self) {
258
+ static VALUE NIO_Selector_backend(VALUE self)
259
+ {
249
260
  struct NIO_Selector *selector;
250
261
 
251
262
  Data_Get_Struct(self, struct NIO_Selector, selector);
252
- if(selector->closed) {
263
+ if (selector->closed) {
253
264
  rb_raise(rb_eIOError, "selector is closed");
254
265
  }
255
266
 
@@ -264,29 +275,33 @@ static VALUE NIO_Selector_backend(VALUE self) {
264
275
  return ID2SYM(rb_intern("select"));
265
276
  case EVBACKEND_PORT:
266
277
  return ID2SYM(rb_intern("port"));
278
+ case EVBACKEND_LINUXAIO:
279
+ return ID2SYM(rb_intern("linuxaio"));
280
+ case EVBACKEND_IOURING:
281
+ return ID2SYM(rb_intern("io_uring"));
267
282
  }
268
283
 
269
284
  return ID2SYM(rb_intern("unknown"));
270
285
  }
271
286
 
272
287
  /* Synchronize around a reentrant selector lock */
273
- static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE *args), VALUE *args)
288
+ static VALUE NIO_Selector_synchronize(VALUE self, VALUE (*func)(VALUE arg), VALUE arg)
274
289
  {
275
290
  VALUE current_thread, lock_holder, lock;
276
291
 
277
292
  current_thread = rb_thread_current();
278
293
  lock_holder = rb_ivar_get(self, rb_intern("lock_holder"));
279
294
 
280
- if(lock_holder != current_thread) {
295
+ if (lock_holder != current_thread) {
281
296
  lock = rb_ivar_get(self, rb_intern("lock"));
282
297
  rb_funcall(lock, rb_intern("lock"), 0);
283
298
  rb_ivar_set(self, rb_intern("lock_holder"), current_thread);
284
299
 
285
300
  /* We've acquired the lock, so ensure we unlock it */
286
- return rb_ensure(func, (VALUE)args, NIO_Selector_unlock, self);
301
+ return rb_ensure(func, (VALUE)arg, NIO_Selector_unlock, self);
287
302
  } else {
288
303
  /* We already hold the selector lock, so no need to unlock it */
289
- return func(args);
304
+ return func(arg);
290
305
  }
291
306
  }
292
307
 
@@ -307,29 +322,30 @@ static VALUE NIO_Selector_unlock(VALUE self)
307
322
  static VALUE NIO_Selector_register(VALUE self, VALUE io, VALUE interests)
308
323
  {
309
324
  VALUE args[3] = {self, io, interests};
310
- return NIO_Selector_synchronize(self, NIO_Selector_register_synchronized, args);
325
+ return NIO_Selector_synchronize(self, NIO_Selector_register_synchronized, (VALUE)args);
311
326
  }
312
327
 
313
328
  /* Internal implementation of register after acquiring mutex */
314
- static VALUE NIO_Selector_register_synchronized(VALUE *args)
329
+ static VALUE NIO_Selector_register_synchronized(VALUE _args)
315
330
  {
316
331
  VALUE self, io, interests, selectables, monitor;
317
332
  VALUE monitor_args[3];
318
333
  struct NIO_Selector *selector;
319
334
 
335
+ VALUE *args = (VALUE *)_args;
320
336
  self = args[0];
321
337
  io = args[1];
322
338
  interests = args[2];
323
339
 
324
340
  Data_Get_Struct(self, struct NIO_Selector, selector);
325
- if(selector->closed) {
341
+ if (selector->closed) {
326
342
  rb_raise(rb_eIOError, "selector is closed");
327
343
  }
328
344
 
329
345
  selectables = rb_ivar_get(self, rb_intern("selectables"));
330
346
  monitor = rb_hash_lookup(selectables, io);
331
347
 
332
- if(monitor != Qnil)
348
+ if (monitor != Qnil)
333
349
  rb_raise(rb_eArgError, "this IO is already registered with selector");
334
350
 
335
351
  /* Create a new NIO::Monitor */
@@ -347,21 +363,22 @@ static VALUE NIO_Selector_register_synchronized(VALUE *args)
347
363
  static VALUE NIO_Selector_deregister(VALUE self, VALUE io)
348
364
  {
349
365
  VALUE args[2] = {self, io};
350
- return NIO_Selector_synchronize(self, NIO_Selector_deregister_synchronized, args);
366
+ return NIO_Selector_synchronize(self, NIO_Selector_deregister_synchronized, (VALUE)args);
351
367
  }
352
368
 
353
369
  /* Internal implementation of register after acquiring mutex */
354
- static VALUE NIO_Selector_deregister_synchronized(VALUE *args)
370
+ static VALUE NIO_Selector_deregister_synchronized(VALUE _args)
355
371
  {
356
372
  VALUE self, io, selectables, monitor;
357
373
 
374
+ VALUE *args = (VALUE *)_args;
358
375
  self = args[0];
359
376
  io = args[1];
360
377
 
361
378
  selectables = rb_ivar_get(self, rb_intern("selectables"));
362
379
  monitor = rb_hash_delete(selectables, io);
363
380
 
364
- if(monitor != Qnil) {
381
+ if (monitor != Qnil) {
365
382
  rb_funcall(monitor, rb_intern("close"), 1, Qfalse);
366
383
  }
367
384
 
@@ -381,49 +398,48 @@ static VALUE NIO_Selector_is_registered(VALUE self, VALUE io)
381
398
  static VALUE NIO_Selector_select(int argc, VALUE *argv, VALUE self)
382
399
  {
383
400
  VALUE timeout;
384
- VALUE args[2];
385
401
 
386
402
  rb_scan_args(argc, argv, "01", &timeout);
387
403
 
388
- if(timeout != Qnil && NUM2DBL(timeout) < 0) {
404
+ if (timeout != Qnil && NUM2DBL(timeout) < 0) {
389
405
  rb_raise(rb_eArgError, "time interval must be positive");
390
406
  }
391
407
 
392
- args[0] = self;
393
- args[1] = timeout;
394
-
395
- return NIO_Selector_synchronize(self, NIO_Selector_select_synchronized, args);
408
+ VALUE args[2] = {self, timeout};
409
+ return NIO_Selector_synchronize(self, NIO_Selector_select_synchronized, (VALUE)args);
396
410
  }
397
411
 
398
412
  /* Internal implementation of select with the selector lock held */
399
- static VALUE NIO_Selector_select_synchronized(VALUE *args)
413
+ static VALUE NIO_Selector_select_synchronized(VALUE _args)
400
414
  {
401
415
  int ready;
402
416
  VALUE ready_array;
403
417
  struct NIO_Selector *selector;
404
418
 
419
+ VALUE *args = (VALUE *)_args;
420
+
405
421
  Data_Get_Struct(args[0], struct NIO_Selector, selector);
406
422
 
407
- if(selector->closed) {
423
+ if (selector->closed) {
408
424
  rb_raise(rb_eIOError, "selector is closed");
409
425
  }
410
426
 
411
- if(!rb_block_given_p()) {
427
+ if (!rb_block_given_p()) {
412
428
  selector->ready_array = rb_ary_new();
413
429
  }
414
430
 
415
431
  ready = NIO_Selector_run(selector, args[1]);
416
432
 
417
433
  /* Timeout */
418
- if(ready < 0) {
419
- if(!rb_block_given_p()) {
434
+ if (ready < 0) {
435
+ if (!rb_block_given_p()) {
420
436
  selector->ready_array = Qnil;
421
437
  }
422
438
 
423
439
  return Qnil;
424
440
  }
425
441
 
426
- if(rb_block_given_p()) {
442
+ if (rb_block_given_p()) {
427
443
  return INT2NUM(ready);
428
444
  } else {
429
445
  ready_array = selector->ready_array;
@@ -441,12 +457,12 @@ static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
441
457
  selector->selecting = 1;
442
458
  selector->wakeup_fired = 0;
443
459
 
444
- if(timeout == Qnil) {
460
+ if (timeout == Qnil) {
445
461
  /* Don't fire a wakeup timeout if we weren't passed one */
446
462
  ev_timer_stop(selector->ev_loop, &selector->timer);
447
463
  } else {
448
464
  timeout_val = NUM2DBL(timeout);
449
- if(timeout_val == 0) {
465
+ if (timeout_val == 0) {
450
466
  /* If we've been given an explicit timeout of 0, perform a non-blocking
451
467
  select operation */
452
468
  ev_run_flags = EVRUN_NOWAIT;
@@ -462,7 +478,7 @@ static int NIO_Selector_run(struct NIO_Selector *selector, VALUE timeout)
462
478
  result = selector->ready_count;
463
479
  selector->selecting = selector->ready_count = 0;
464
480
 
465
- if(result > 0 || selector->wakeup_fired) {
481
+ if (result > 0 || selector->wakeup_fired) {
466
482
  selector->wakeup_fired = 0;
467
483
  return result;
468
484
  } else {
@@ -476,7 +492,7 @@ static VALUE NIO_Selector_wakeup(VALUE self)
476
492
  struct NIO_Selector *selector;
477
493
  Data_Get_Struct(self, struct NIO_Selector, selector);
478
494
 
479
- if(selector->closed) {
495
+ if (selector->closed) {
480
496
  rb_raise(rb_eIOError, "selector is closed");
481
497
  }
482
498
 
@@ -489,14 +505,13 @@ static VALUE NIO_Selector_wakeup(VALUE self)
489
505
  /* Close the selector and free system resources */
490
506
  static VALUE NIO_Selector_close(VALUE self)
491
507
  {
492
- VALUE args[1] = {self};
493
- return NIO_Selector_synchronize(self, NIO_Selector_close_synchronized, args);
508
+ return NIO_Selector_synchronize(self, NIO_Selector_close_synchronized, self);
494
509
  }
495
510
 
496
- static VALUE NIO_Selector_close_synchronized(VALUE *args)
511
+ static VALUE NIO_Selector_close_synchronized(VALUE self)
497
512
  {
498
513
  struct NIO_Selector *selector;
499
- VALUE self = args[0];
514
+
500
515
  Data_Get_Struct(self, struct NIO_Selector, selector);
501
516
 
502
517
  NIO_Selector_shutdown(selector);
@@ -507,14 +522,13 @@ static VALUE NIO_Selector_close_synchronized(VALUE *args)
507
522
  /* Is the selector closed? */
508
523
  static VALUE NIO_Selector_closed(VALUE self)
509
524
  {
510
- VALUE args[1] = {self};
511
- return NIO_Selector_synchronize(self, NIO_Selector_closed_synchronized, args);
525
+ return NIO_Selector_synchronize(self, NIO_Selector_closed_synchronized, self);
512
526
  }
513
527
 
514
- static VALUE NIO_Selector_closed_synchronized(VALUE *args)
528
+ static VALUE NIO_Selector_closed_synchronized(VALUE self)
515
529
  {
516
530
  struct NIO_Selector *selector;
517
- VALUE self = args[0];
531
+
518
532
  Data_Get_Struct(self, struct NIO_Selector, selector);
519
533
 
520
534
  return selector->closed ? Qtrue : Qfalse;
@@ -528,7 +542,6 @@ static VALUE NIO_Selector_is_empty(VALUE self)
528
542
  return rb_funcall(selectables, rb_intern("empty?"), 0) == Qtrue ? Qtrue : Qfalse;
529
543
  }
530
544
 
531
-
532
545
  /* Called whenever a timeout fires on the event loop */
533
546
  static void NIO_Selector_timeout_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents)
534
547
  {
@@ -542,7 +555,8 @@ static void NIO_Selector_wakeup_callback(struct ev_loop *ev_loop, struct ev_io *
542
555
  selector->selecting = 0;
543
556
 
544
557
  /* Drain the wakeup pipe, giving us level-triggered behavior */
545
- while(read(selector->wakeup_reader, buffer, 128) > 0);
558
+ while (read(selector->wakeup_reader, buffer, 128) > 0)
559
+ ;
546
560
  }
547
561
 
548
562
  /* libev callback fired whenever a monitor gets an event */
@@ -558,7 +572,7 @@ void NIO_Selector_monitor_callback(struct ev_loop *ev_loop, struct ev_io *io, in
558
572
  selector->ready_count++;
559
573
  monitor_data->revents = revents;
560
574
 
561
- if(rb_block_given_p()) {
575
+ if (rb_block_given_p()) {
562
576
  rb_yield(monitor);
563
577
  } else {
564
578
  assert(selector->ready_array != Qnil);
@@ -24,6 +24,7 @@ module NIO
24
24
  # @return [NIO::ByteBuffer]
25
25
  def initialize(capacity)
26
26
  raise TypeError, "no implicit conversion of #{capacity.class} to Integer" unless capacity.is_a?(Integer)
27
+
27
28
  @capacity = capacity
28
29
  clear
29
30
  end
@@ -119,9 +120,11 @@ module NIO
119
120
  # @return [self]
120
121
  def put(str)
121
122
  raise TypeError, "expected String, got #{str.class}" unless str.respond_to?(:to_str)
123
+
122
124
  str = str.to_str
123
125
 
124
126
  raise OverflowError, "buffer is full" if str.length > @limit - @position
127
+
125
128
  @buffer[@position...str.length] = str
126
129
  @position += str.length
127
130
  self
@@ -188,6 +191,7 @@ module NIO
188
191
  # @raise [NIO::ByteBuffer::MarkUnsetError] mark has not been set (call `#mark` first)
189
192
  def reset
190
193
  raise MarkUnsetError, "mark has not been set" unless @mark
194
+
191
195
  @position = @mark
192
196
  self
193
197
  end
data/lib/nio/monitor.rb CHANGED
@@ -8,7 +8,7 @@ module NIO
8
8
 
9
9
  # :nodoc:
10
10
  def initialize(io, interests, selector)
11
- unless io.is_a? OpenSSL::SSL::SSLSocket
11
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
12
12
  unless io.is_a?(IO)
13
13
  if IO.respond_to? :try_convert
14
14
  io = IO.try_convert(io)
data/lib/nio/selector.rb CHANGED
@@ -14,7 +14,7 @@ module NIO
14
14
 
15
15
  # Create a new NIO::Selector
16
16
  def initialize(backend = :ruby)
17
- raise ArgumentError, "unsupported backend: #{backend}" unless backend == :ruby
17
+ raise ArgumentError, "unsupported backend: #{backend}" unless [:ruby, nil].include?(backend)
18
18
 
19
19
  @selectables = {}
20
20
  @lock = Mutex.new
@@ -26,14 +26,16 @@ module NIO
26
26
 
27
27
  # Return a symbol representing the backend I/O multiplexing mechanism used.
28
28
  # 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
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
+ # * :linuxaio - libev w\ Linux AIO io_submit (experimental)
37
+ # * :io_uring - libev w\ Linux io_uring (experimental)
38
+ # * :unknown - libev w\ unknown backend
37
39
  def backend
38
40
  :ruby
39
41
  end
@@ -44,7 +46,7 @@ module NIO
44
46
  # * :w - is the IO writeable?
45
47
  # * :rw - is the IO either readable or writeable?
46
48
  def register(io, interest)
47
- unless io.is_a? OpenSSL::SSL::SSLSocket
49
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
48
50
  io = IO.try_convert(io)
49
51
  end
50
52
 
data/lib/nio/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NIO
4
- VERSION = "2.5.2"
4
+ VERSION = "2.5.9"
5
5
  end
data/lib/nio.rb CHANGED
@@ -12,9 +12,28 @@ module NIO
12
12
  def self.engine
13
13
  ENGINE
14
14
  end
15
+
16
+ def self.pure?(env = ENV)
17
+ # The user has explicitly opted in to non-native implementation:
18
+ if env["NIO4R_PURE"] == "true"
19
+ return true
20
+ end
21
+
22
+ # Native Ruby on Windows is not supported:
23
+ if (Gem.win_platform? && !defined?(JRUBY_VERSION))
24
+ return true
25
+ end
26
+
27
+ # M1 native extension is crashing on M1 (arm64):
28
+ # if RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM =~ /arm64/
29
+ # return true
30
+ # end
31
+
32
+ return false
33
+ end
15
34
  end
16
35
 
17
- if ENV["NIO4R_PURE"] == "true" || (Gem.win_platform? && !defined?(JRUBY_VERSION))
36
+ if NIO.pure?
18
37
  require "nio/monitor"
19
38
  require "nio/selector"
20
39
  require "nio/bytebuffer"
data/license.md ADDED
@@ -0,0 +1,66 @@
1
+ # MIT License
2
+
3
+ Copyright, 2011-2020, by Tony Arcieri.
4
+ Copyright, 2012, by Logan Bowers.
5
+ Copyright, 2013, by FURUHASHI Sadayuki.
6
+ Copyright, 2013, by Stephen von Takach.
7
+ Copyright, 2013, by Tim Carey-Smith.
8
+ Copyright, 2013, by brainopia.
9
+ Copyright, 2013, by Luis Lavena.
10
+ Copyright, 2014, by SHIBATA Hiroshi.
11
+ Copyright, 2014, by Sergey Avseyev.
12
+ Copyright, 2014, by JohnnyT.
13
+ Copyright, 2015-2017, by Tiago Cardoso.
14
+ Copyright, 2015, by Daniel Berger.
15
+ Copyright, 2015, by Upekshe.
16
+ Copyright, 2015-2016, by UpeksheJay.
17
+ Copyright, 2015, by Vladimir Kochnev.
18
+ Copyright, 2016-2018, by Jun Aruga.
19
+ Copyright, 2016, by Omer Katz.
20
+ Copyright, 2016-2021, by Olle Jonsson.
21
+ Copyright, 2017, by usa.
22
+ Copyright, 2017, by HoneyryderChuck.
23
+ Copyright, 2017, by tompng.
24
+ Copyright, 2018-2021, by Samuel Williams.
25
+ Copyright, 2019, by Cédric Boutillier.
26
+ Copyright, 2019-2020, by MSP-Greg.
27
+ Copyright, 2019-2020, by Benoit Daloze.
28
+ Copyright, 2019, by Jesús Burgos Maciá.
29
+ Copyright, 2019, by Thomas Kuntz.
30
+ Copyright, 2019, by Orien Madgwick.
31
+ Copyright, 2019, by Thomas Dziedzic.
32
+ Copyright, 2019, by Zhang Kang.
33
+ Copyright, 2020, by eladeyal-intel.
34
+ Copyright, 2020, by Pedro Paiva.
35
+ Copyright, 2020, by Bo.
36
+ Copyright, 2020, by Charles Oliver Nutter.
37
+ Copyright, 2020-2021, by Joao Fernandes.
38
+ Copyright, 2021, by Jun Jiang.
39
+ Copyright, 2021, by Jeffrey Martin.
40
+ Copyright, 2021, by Pavel Lobashov.
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining a copy
43
+ of this software and associated documentation files (the "Software"), to deal
44
+ in the Software without restriction, including without limitation the rights
45
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46
+ copies of the Software, and to permit persons to whom the Software is
47
+ furnished to do so, subject to the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be included in all
50
+ copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
58
+ SOFTWARE.
59
+
60
+ ## libev
61
+
62
+ Released under the BSD license. See [ext/libev/LICENSE] for details.
63
+
64
+ Copyright, 2007-2019, by Marc Alexander Lehmann.
65
+
66
+ [ext/libev/LICENSE]: https://github.com/socketry/nio4r/blob/master/ext/libev/LICENSE
data/nio4r.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path("../lib/nio/version", __FILE__)
3
+ require File.expand_path("lib/nio/version", __dir__)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.authors = ["Tony Arcieri"]
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  "wiki_uri" => "https://github.com/socketry/nio4r/wiki"
29
29
  }
30
30
 
31
- spec.required_ruby_version = ">= 2.3"
31
+ spec.required_ruby_version = ">= 2.4"
32
32
 
33
33
  if defined? JRUBY_VERSION
34
34
  spec.files << "lib/nio4r_ext.jar"
@@ -4,8 +4,7 @@ if defined? JRUBY_VERSION
4
4
  require "rake/javaextensiontask"
5
5
  Rake::JavaExtensionTask.new("nio4r_ext") do |ext|
6
6
  ext.ext_dir = "ext/nio4r"
7
- ext.source_version = "1.8"
8
- ext.target_version = "1.8"
7
+ ext.release = '8'
9
8
  end
10
9
  else
11
10
  require "rake/extensiontask"
@@ -352,4 +352,3 @@ RSpec.describe NIO::ByteBuffer do
352
352
  end
353
353
  end
354
354
  end
355
- # rubocop:enable Metrics/BlockLength