io-event 1.0.9 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f83ab57c44b58bfd257acaa093dddf3f2b2b9ee444b64abacd2a872a741d429
4
- data.tar.gz: 85e665f83983f2796001f84a9199a7f285c7e641920d647762785b6cd5e7253e
3
+ metadata.gz: 529ab26d211811182c1ac8b7b292431533c830eddcfd8781185c9ea4ff623c93
4
+ data.tar.gz: cef3ea8d930d3f3f92e0c814c0f89405a78e3da1d4ebd6c0d1e73bd32f6839a6
5
5
  SHA512:
6
- metadata.gz: f73a3744ed94bec2a42c0ef405d7bf14c1f58d3f2ac04edc28c4fc97de21a6cb7f8e6c142ef8477f93a044b17a6d5c27fc372b8b8f7545228e9e0885ef0f4fc6
7
- data.tar.gz: 555b411452da5fc65a425d37fae32af486bdcf3c4e9d5721c48a927847420eb1d5bdf0c668fdd13d25ac7551d7b127d7d050b540d580d5db689b2ff04d8130f0
6
+ metadata.gz: 77cd0725f41f507e391f54dae4071c9b2721a1fc4ce1c4dbcbf7b4dac8a7453c0e4867679b9f9c615d82ce06af2b3f77745b0d1526f0c6bb02cf06a60c84f763
7
+ data.tar.gz: 6d9a389303af3b13540ff2761d8e35762e3af975c7e1defddf8765088129f43dc4584029947bafd2a6eb35c60f8206b0dc184d425c52163d1652392e62bb9333
checksums.yaml.gz.sig CHANGED
Binary file
data/design.md ADDED
@@ -0,0 +1,63 @@
1
+ ## Dual `_select` without GVL:
2
+
3
+ Always release GVL:
4
+
5
+ ```
6
+ Warming up --------------------------------------
7
+ KQueue 55.896k i/100ms
8
+ Select 17.023k i/100ms
9
+ Calculating -------------------------------------
10
+ KQueue 532.515k (± 8.0%) i/s - 2.683M in 5.071193s
11
+ Select 177.956k (± 3.4%) i/s - 902.219k in 5.075817s
12
+
13
+ Comparison:
14
+ KQueue: 532515.3 i/s
15
+ Select: 177956.1 i/s - 2.99x (± 0.00) slower
16
+ ```
17
+
18
+ Only release GVL with non-zero timeout, with selector.elect(1) (so always hitting slow path):
19
+
20
+ ```
21
+ Warming up --------------------------------------
22
+ KQueue 39.628k i/100ms
23
+ Select 18.330k i/100ms
24
+ Calculating -------------------------------------
25
+ KQueue 381.868k (± 6.5%) i/s - 1.902M in 5.004267s
26
+ Select 171.623k (± 3.0%) i/s - 861.510k in 5.024308s
27
+
28
+ Comparison:
29
+ KQueue: 381867.8 i/s
30
+ Select: 171622.5 i/s - 2.23x (± 0.00) slower
31
+ ```
32
+
33
+ Only release GVL with non-zero timeout, with selector.select(0) so always hitting fast path:
34
+
35
+ ```
36
+ Warming up --------------------------------------
37
+ KQueue 56.240k i/100ms
38
+ Select 17.888k i/100ms
39
+ Calculating -------------------------------------
40
+ KQueue 543.042k (± 7.8%) i/s - 2.700M in 5.003790s
41
+ Select 171.866k (± 4.3%) i/s - 858.624k in 5.005785s
42
+
43
+ Comparison:
44
+ KQueue: 543041.5 i/s
45
+ Select: 171866.2 i/s - 3.16x (± 0.00) slower
46
+ ```
47
+
48
+ Only release GVL when no events are ready and non-zero timeout, with selector.select(1):
49
+
50
+ ```
51
+ Warming up --------------------------------------
52
+ KQueue 53.401k i/100ms
53
+ Select 16.691k i/100ms
54
+ Calculating -------------------------------------
55
+ KQueue 524.564k (± 6.1%) i/s - 2.617M in 5.006996s
56
+ Select 179.329k (± 2.4%) i/s - 901.314k in 5.029136s
57
+
58
+ Comparison:
59
+ KQueue: 524564.0 i/s
60
+ Select: 179329.1 i/s - 2.93x (± 0.00) slower
61
+ ```
62
+
63
+ So this approach seems to be a net win of about 1.5x throughput.
data/ext/extconf.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2021, by Samuel Williams.
2
6
 
3
7
  # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
8
  #
@@ -385,7 +385,7 @@ VALUE IO_Event_Selector_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
385
385
  return rb_ensure(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_ensure, (VALUE)&io_wait_arguments);
386
386
  }
387
387
 
388
- #ifdef HAVE_RUBY_IO_BUFFER_H
388
+ #ifdef RUBY_FIBER_SCHEDULER_VERSION
389
389
 
390
390
  struct io_read_arguments {
391
391
  VALUE self;
@@ -398,6 +398,7 @@ struct io_read_arguments {
398
398
 
399
399
  VALUE buffer;
400
400
  size_t length;
401
+ size_t offset;
401
402
  };
402
403
 
403
404
  static
@@ -408,8 +409,8 @@ VALUE io_read_loop(VALUE _arguments) {
408
409
  size_t size;
409
410
  rb_io_buffer_get_bytes_for_writing(arguments->buffer, &base, &size);
410
411
 
411
- size_t offset = 0;
412
412
  size_t length = arguments->length;
413
+ size_t offset = arguments->offset;
413
414
 
414
415
  while (true) {
415
416
  size_t maximum_size = size - offset;
@@ -440,9 +441,10 @@ VALUE io_read_ensure(VALUE _arguments) {
440
441
  return Qnil;
441
442
  }
442
443
 
443
- VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
444
+ VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
444
445
  int descriptor = IO_Event_Selector_io_descriptor(io);
445
446
 
447
+ size_t offset = NUM2SIZET(_offset);
446
448
  size_t length = NUM2SIZET(_length);
447
449
 
448
450
  struct io_read_arguments io_read_arguments = {
@@ -454,11 +456,25 @@ VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
454
456
  .descriptor = descriptor,
455
457
  .buffer = buffer,
456
458
  .length = length,
459
+ .offset = offset,
457
460
  };
458
461
 
459
462
  return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
460
463
  }
461
464
 
465
+ VALUE IO_Event_Selector_EPoll_io_read_compatible(int argc, VALUE *argv, VALUE self)
466
+ {
467
+ rb_check_arity(argc, 4, 5);
468
+
469
+ VALUE _offset = SIZET2NUM(0);
470
+
471
+ if (argc == 5) {
472
+ _offset = argv[4];
473
+ }
474
+
475
+ return IO_Event_Selector_EPoll_io_read(self, argv[0], argv[1], argv[2], argv[3], _offset);
476
+ }
477
+
462
478
  struct io_write_arguments {
463
479
  VALUE self;
464
480
  VALUE fiber;
@@ -470,6 +486,7 @@ struct io_write_arguments {
470
486
 
471
487
  VALUE buffer;
472
488
  size_t length;
489
+ size_t offset;
473
490
  };
474
491
 
475
492
  static
@@ -480,8 +497,8 @@ VALUE io_write_loop(VALUE _arguments) {
480
497
  size_t size;
481
498
  rb_io_buffer_get_bytes_for_reading(arguments->buffer, &base, &size);
482
499
 
483
- size_t offset = 0;
484
500
  size_t length = arguments->length;
501
+ size_t offset = arguments->offset;
485
502
 
486
503
  if (length > size) {
487
504
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
@@ -516,10 +533,11 @@ VALUE io_write_ensure(VALUE _arguments) {
516
533
  return Qnil;
517
534
  };
518
535
 
519
- VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
536
+ VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
520
537
  int descriptor = IO_Event_Selector_io_descriptor(io);
521
538
 
522
539
  size_t length = NUM2SIZET(_length);
540
+ size_t offset = NUM2SIZET(_offset);
523
541
 
524
542
  struct io_write_arguments io_write_arguments = {
525
543
  .self = self,
@@ -530,11 +548,25 @@ VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
530
548
  .descriptor = descriptor,
531
549
  .buffer = buffer,
532
550
  .length = length,
551
+ .offset = offset,
533
552
  };
534
553
 
535
554
  return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
536
555
  }
537
556
 
557
+ VALUE IO_Event_Selector_EPoll_io_write_compatible(int argc, VALUE *argv, VALUE self)
558
+ {
559
+ rb_check_arity(argc, 4, 5);
560
+
561
+ VALUE _offset = SIZET2NUM(0);
562
+
563
+ if (argc == 5) {
564
+ _offset = argv[4];
565
+ }
566
+
567
+ return IO_Event_Selector_EPoll_io_write(self, argv[0], argv[1], argv[2], argv[3], _offset);
568
+ }
569
+
538
570
  #endif
539
571
 
540
572
  static
@@ -683,11 +715,13 @@ void Init_IO_Event_Selector_EPoll(VALUE IO_Event_Selector) {
683
715
  rb_define_method(IO_Event_Selector_EPoll, "close", IO_Event_Selector_EPoll_close, 0);
684
716
 
685
717
  rb_define_method(IO_Event_Selector_EPoll, "io_wait", IO_Event_Selector_EPoll_io_wait, 3);
718
+
719
+ rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read_compatible, -1);
720
+ rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write_compatible, -1);
686
721
 
687
- #ifdef HAVE_RUBY_IO_BUFFER_H
688
- rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read, 4);
689
- rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write, 4);
690
- #endif
722
+ // Once compatibility isn't a concern, we can do this:
723
+ // rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read, 5);
724
+ // rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write, 5);
691
725
 
692
726
  rb_define_method(IO_Event_Selector_EPoll, "process_wait", IO_Event_Selector_EPoll_process_wait, 3);
693
727
  }
@@ -380,7 +380,7 @@ VALUE IO_Event_Selector_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE
380
380
  return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
381
381
  }
382
382
 
383
- #ifdef HAVE_RUBY_IO_BUFFER_H
383
+ #ifdef RUBY_FIBER_SCHEDULER_VERSION
384
384
 
385
385
  struct io_read_arguments {
386
386
  VALUE self;
@@ -393,6 +393,7 @@ struct io_read_arguments {
393
393
 
394
394
  VALUE buffer;
395
395
  size_t length;
396
+ size_t offset;
396
397
  };
397
398
 
398
399
  static
@@ -403,8 +404,8 @@ VALUE io_read_loop(VALUE _arguments) {
403
404
  size_t size;
404
405
  rb_io_buffer_get_bytes_for_writing(arguments->buffer, &base, &size);
405
406
 
406
- size_t offset = 0;
407
407
  size_t length = arguments->length;
408
+ size_t offset = arguments->offset;
408
409
 
409
410
  if (DEBUG_IO_READ) fprintf(stderr, "io_read_loop(fd=%d, length=%zu)\n", arguments->descriptor, length);
410
411
 
@@ -442,13 +443,14 @@ VALUE io_read_ensure(VALUE _arguments) {
442
443
  return Qnil;
443
444
  }
444
445
 
445
- VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
446
+ VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
446
447
  struct IO_Event_Selector_KQueue *data = NULL;
447
448
  TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, data);
448
449
 
449
450
  int descriptor = IO_Event_Selector_io_descriptor(io);
450
451
 
451
452
  size_t length = NUM2SIZET(_length);
453
+ size_t offset = NUM2SIZET(_offset);
452
454
 
453
455
  struct io_read_arguments io_read_arguments = {
454
456
  .self = self,
@@ -459,11 +461,25 @@ VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE
459
461
  .descriptor = descriptor,
460
462
  .buffer = buffer,
461
463
  .length = length,
464
+ .offset = offset,
462
465
  };
463
466
 
464
467
  return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
465
468
  }
466
469
 
470
+ static VALUE IO_Event_Selector_KQueue_io_read_compatible(int argc, VALUE *argv, VALUE self)
471
+ {
472
+ rb_check_arity(argc, 4, 5);
473
+
474
+ VALUE _offset = SIZET2NUM(0);
475
+
476
+ if (argc == 5) {
477
+ _offset = argv[4];
478
+ }
479
+
480
+ return IO_Event_Selector_KQueue_io_read(self, argv[0], argv[1], argv[2], argv[3], _offset);
481
+ }
482
+
467
483
  struct io_write_arguments {
468
484
  VALUE self;
469
485
  VALUE fiber;
@@ -475,6 +491,7 @@ struct io_write_arguments {
475
491
 
476
492
  VALUE buffer;
477
493
  size_t length;
494
+ size_t offset;
478
495
  };
479
496
 
480
497
  static
@@ -485,8 +502,8 @@ VALUE io_write_loop(VALUE _arguments) {
485
502
  size_t size;
486
503
  rb_io_buffer_get_bytes_for_reading(arguments->buffer, &base, &size);
487
504
 
488
- size_t offset = 0;
489
505
  size_t length = arguments->length;
506
+ size_t offset = arguments->offset;
490
507
 
491
508
  if (length > size) {
492
509
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
@@ -528,13 +545,14 @@ VALUE io_write_ensure(VALUE _arguments) {
528
545
  return Qnil;
529
546
  };
530
547
 
531
- VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
548
+ VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
532
549
  struct IO_Event_Selector_KQueue *data = NULL;
533
550
  TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, data);
534
551
 
535
552
  int descriptor = IO_Event_Selector_io_descriptor(io);
536
553
 
537
554
  size_t length = NUM2SIZET(_length);
555
+ size_t offset = NUM2SIZET(_offset);
538
556
 
539
557
  struct io_write_arguments io_write_arguments = {
540
558
  .self = self,
@@ -545,11 +563,25 @@ VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
545
563
  .descriptor = descriptor,
546
564
  .buffer = buffer,
547
565
  .length = length,
566
+ .offset = offset,
548
567
  };
549
568
 
550
569
  return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
551
570
  }
552
571
 
572
+ static VALUE IO_Event_Selector_KQueue_io_write_compatible(int argc, VALUE *argv, VALUE self)
573
+ {
574
+ rb_check_arity(argc, 4, 5);
575
+
576
+ VALUE _offset = SIZET2NUM(0);
577
+
578
+ if (argc == 5) {
579
+ _offset = argv[4];
580
+ }
581
+
582
+ return IO_Event_Selector_KQueue_io_write(self, argv[0], argv[1], argv[2], argv[3], _offset);
583
+ }
584
+
553
585
  #endif
554
586
 
555
587
  static
@@ -732,11 +764,9 @@ void Init_IO_Event_Selector_KQueue(VALUE IO_Event_Selector) {
732
764
  rb_define_method(IO_Event_Selector_KQueue, "close", IO_Event_Selector_KQueue_close, 0);
733
765
 
734
766
  rb_define_method(IO_Event_Selector_KQueue, "io_wait", IO_Event_Selector_KQueue_io_wait, 3);
735
-
736
- #ifdef HAVE_RUBY_IO_BUFFER_H
737
- rb_define_method(IO_Event_Selector_KQueue, "io_read", IO_Event_Selector_KQueue_io_read, 4);
738
- rb_define_method(IO_Event_Selector_KQueue, "io_write", IO_Event_Selector_KQueue_io_write, 4);
739
- #endif
767
+
768
+ rb_define_method(IO_Event_Selector_KQueue, "io_read", IO_Event_Selector_KQueue_io_read_compatible, -1);
769
+ rb_define_method(IO_Event_Selector_KQueue, "io_write", IO_Event_Selector_KQueue_io_write_compatible, -1);
740
770
 
741
771
  rb_define_method(IO_Event_Selector_KQueue, "process_wait", IO_Event_Selector_KQueue_process_wait, 3);
742
772
  }
@@ -29,6 +29,10 @@
29
29
  #include <ruby/fiber/scheduler.h>
30
30
  #endif
31
31
 
32
+ #ifndef RUBY_FIBER_SCHEDULER_VERSION
33
+ #define RUBY_FIBER_SCHEDULER_VERSION 1
34
+ #endif
35
+
32
36
  #include <time.h>
33
37
 
34
38
  enum IO_Event {
@@ -23,6 +23,7 @@
23
23
 
24
24
  #include <liburing.h>
25
25
  #include <poll.h>
26
+ #include <stdint.h>
26
27
  #include <time.h>
27
28
 
28
29
  #include "pidfd.c"
@@ -324,7 +325,7 @@ VALUE io_wait_rescue(VALUE _arguments, VALUE exception) {
324
325
 
325
326
  if (DEBUG) fprintf(stderr, "io_wait_rescue:io_uring_prep_poll_remove(%p)\n", (void*)arguments->fiber);
326
327
 
327
- io_uring_prep_poll_remove(sqe, (void*)arguments->fiber);
328
+ io_uring_prep_poll_remove(sqe, (uintptr_t)arguments->fiber);
328
329
  io_uring_submit_now(data);
329
330
 
330
331
  rb_exc_raise(exception);
@@ -375,7 +376,7 @@ VALUE IO_Event_Selector_URing_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
375
376
  return rb_rescue(io_wait_transfer, (VALUE)&io_wait_arguments, io_wait_rescue, (VALUE)&io_wait_arguments);
376
377
  }
377
378
 
378
- #ifdef HAVE_RUBY_IO_BUFFER_H
379
+ #ifdef RUBY_FIBER_SCHEDULER_VERSION
379
380
 
380
381
  #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,16,0)
381
382
  static inline off_t io_seekable(int descriptor) {
@@ -408,7 +409,7 @@ static int io_read(struct IO_Event_Selector_URing *data, VALUE fiber, int descri
408
409
  return RB_NUM2INT(result);
409
410
  }
410
411
 
411
- VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
412
+ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
412
413
  struct IO_Event_Selector_URing *data = NULL;
413
414
  TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, data);
414
415
 
@@ -418,8 +419,8 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
418
419
  size_t size;
419
420
  rb_io_buffer_get_bytes_for_writing(buffer, &base, &size);
420
421
 
421
- size_t offset = 0;
422
422
  size_t length = NUM2SIZET(_length);
423
+ size_t offset = NUM2SIZET(_offset);
423
424
 
424
425
  while (true) {
425
426
  size_t maximum_size = size - offset;
@@ -443,6 +444,19 @@ VALUE IO_Event_Selector_URing_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
443
444
  return rb_fiber_scheduler_io_result(offset, 0);
444
445
  }
445
446
 
447
+ static VALUE IO_Event_Selector_URing_io_read_compatible(int argc, VALUE *argv, VALUE self)
448
+ {
449
+ rb_check_arity(argc, 4, 5);
450
+
451
+ VALUE _offset = SIZET2NUM(0);
452
+
453
+ if (argc == 5) {
454
+ _offset = argv[4];
455
+ }
456
+
457
+ return IO_Event_Selector_URing_io_read(self, argv[0], argv[1], argv[2], argv[3], _offset);
458
+ }
459
+
446
460
  static
447
461
  int io_write(struct IO_Event_Selector_URing *data, VALUE fiber, int descriptor, char *buffer, size_t length) {
448
462
  struct io_uring_sqe *sqe = io_get_sqe(data);
@@ -459,7 +473,7 @@ int io_write(struct IO_Event_Selector_URing *data, VALUE fiber, int descriptor,
459
473
  return result;
460
474
  }
461
475
 
462
- VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length) {
476
+ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _length, VALUE _offset) {
463
477
  struct IO_Event_Selector_URing *data = NULL;
464
478
  TypedData_Get_Struct(self, struct IO_Event_Selector_URing, &IO_Event_Selector_URing_Type, data);
465
479
 
@@ -469,8 +483,8 @@ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
469
483
  size_t size;
470
484
  rb_io_buffer_get_bytes_for_reading(buffer, &base, &size);
471
485
 
472
- size_t offset = 0;
473
486
  size_t length = NUM2SIZET(_length);
487
+ size_t offset = NUM2SIZET(_offset);
474
488
 
475
489
  if (length > size) {
476
490
  rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
@@ -496,6 +510,19 @@ VALUE IO_Event_Selector_URing_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
496
510
  return rb_fiber_scheduler_io_result(offset, 0);
497
511
  }
498
512
 
513
+ static VALUE IO_Event_Selector_URing_io_write_compatible(int argc, VALUE *argv, VALUE self)
514
+ {
515
+ rb_check_arity(argc, 4, 5);
516
+
517
+ VALUE _offset = SIZET2NUM(0);
518
+
519
+ if (argc == 5) {
520
+ _offset = argv[4];
521
+ }
522
+
523
+ return IO_Event_Selector_URing_io_write(self, argv[0], argv[1], argv[2], argv[3], _offset);
524
+ }
525
+
499
526
  #endif
500
527
 
501
528
  static const int ASYNC_CLOSE = 1;
@@ -710,11 +737,9 @@ void Init_IO_Event_Selector_URing(VALUE IO_Event_Selector) {
710
737
  rb_define_method(IO_Event_Selector_URing, "close", IO_Event_Selector_URing_close, 0);
711
738
 
712
739
  rb_define_method(IO_Event_Selector_URing, "io_wait", IO_Event_Selector_URing_io_wait, 3);
713
-
714
- #ifdef HAVE_RUBY_IO_BUFFER_H
715
- rb_define_method(IO_Event_Selector_URing, "io_read", IO_Event_Selector_URing_io_read, 4);
716
- rb_define_method(IO_Event_Selector_URing, "io_write", IO_Event_Selector_URing_io_write, 4);
717
- #endif
740
+
741
+ rb_define_method(IO_Event_Selector_URing, "io_read", IO_Event_Selector_URing_io_read_compatible, -1);
742
+ rb_define_method(IO_Event_Selector_URing, "io_write", IO_Event_Selector_URing_io_write_compatible, -1);
718
743
 
719
744
  rb_define_method(IO_Event_Selector_URing, "io_close", IO_Event_Selector_URing_io_close, 1);
720
745
 
@@ -1,22 +1,9 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021-2022, by Samuel Williams.
5
+
6
+ require_relative '../support'
20
7
 
21
8
  module IO::Event
22
9
  module Debug
@@ -80,14 +67,16 @@ module IO::Event
80
67
  @selector.io_wait(fiber, io, events)
81
68
  end
82
69
 
83
- if IO.const_defined?(:Buffer)
84
- def io_read(fiber, io, buffer, length)
85
- @selector.io_read(fiber, io, buffer, length)
86
- end
87
-
88
- def io_write(fiber, io, buffer, length)
89
- @selector.io_write(fiber, io, buffer, length)
90
- end
70
+ def io_read(...)
71
+ @selector.io_read(...)
72
+ end
73
+
74
+ def io_write(...)
75
+ @selector.io_write(...)
76
+ end
77
+
78
+ def respond_to?(name, include_private = false)
79
+ @selector.respond_to?(name, include_private)
91
80
  end
92
81
 
93
82
  def select(duration = nil)
@@ -1,22 +1,7 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021, by Samuel Williams.
20
5
 
21
6
  module IO::Event
22
7
  # A thread safe synchronisation primative.
@@ -1,24 +1,12 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021-2022, by Samuel Williams.
20
5
 
21
6
  require_relative '../interrupt'
7
+ require_relative '../support'
8
+
9
+ require 'io/nonblock'
22
10
 
23
11
  module IO::Event
24
12
  module Selector
@@ -36,7 +24,7 @@ module IO::Event
36
24
 
37
25
  attr :loop
38
26
 
39
- # If the event loop is currently blocked,
27
+ # If the event loop is currently sleeping, wake it up.
40
28
  def wakeup
41
29
  if @blocked
42
30
  @interrupt.signal
@@ -148,11 +136,65 @@ module IO::Event
148
136
  waiter&.invalidate
149
137
  end
150
138
 
151
- if IO.const_defined?(:Buffer)
139
+ if Support.fiber_scheduler_v2?
152
140
  EAGAIN = Errno::EAGAIN::Errno
153
141
 
154
- def io_read(fiber, io, buffer, length)
155
- offset = 0
142
+ def io_read(fiber, io, buffer, length, offset = 0)
143
+ total = 0
144
+ io.nonblock = true
145
+
146
+ while true
147
+ maximum_size = buffer.size - offset
148
+ result = Fiber.blocking{buffer.read(io, maximum_size, offset)}
149
+
150
+ if result == -EAGAIN
151
+ if length > 0
152
+ self.io_wait(fiber, io, IO::READABLE)
153
+ else
154
+ return result
155
+ end
156
+ elsif result < 0
157
+ return result
158
+ else
159
+ total += result
160
+ offset += result
161
+ break if total >= length
162
+ end
163
+ end
164
+
165
+ return total
166
+ end
167
+
168
+ def io_write(fiber, io, buffer, length, offset = 0)
169
+ total = 0
170
+ io.nonblock = true
171
+
172
+ while true
173
+ maximum_size = buffer.size - offset
174
+ result = Fiber.blocking{buffer.write(io, maximum_size, offset)}
175
+
176
+ if result == -EAGAIN
177
+ if length > 0
178
+ self.io_wait(fiber, io, IO::READABLE)
179
+ else
180
+ return result
181
+ end
182
+ elsif result < 0
183
+ return result
184
+ else
185
+ total += result
186
+ offset += result
187
+ break if total >= length
188
+ end
189
+ end
190
+
191
+ return offset
192
+ end
193
+ elsif Support.fiber_scheduler_v1?
194
+ EAGAIN = Errno::EAGAIN::Errno
195
+
196
+ def io_read(fiber, _io, buffer, length, offset = 0)
197
+ io = IO.for_fd(_io.fileno, autoclose: false)
156
198
 
157
199
  while true
158
200
  maximum_size = buffer.size - offset
@@ -185,8 +227,8 @@ module IO::Event
185
227
  return offset
186
228
  end
187
229
 
188
- def io_write(fiber, io, buffer, length)
189
- offset = 0
230
+ def io_write(fiber, _io, buffer, length, offset = 0)
231
+ io = IO.for_fd(_io.fileno, autoclose: false)
190
232
 
191
233
  while true
192
234
  maximum_size = buffer.size - offset
@@ -214,24 +256,17 @@ module IO::Event
214
256
 
215
257
  return offset
216
258
  end
259
+
260
+ def blocking(&block)
261
+ fiber = Fiber.new(blocking: true, &block)
262
+ return fiber.resume(fiber)
263
+ end
217
264
  end
218
265
 
219
266
  def process_wait(fiber, pid, flags)
220
- r, w = IO.pipe
221
-
222
- thread = Thread.new do
267
+ Thread.new do
223
268
  Process::Status.wait(pid, flags)
224
- ensure
225
- w.close
226
- end
227
-
228
- self.io_wait(fiber, r, IO::READABLE)
229
-
230
- return thread.value
231
- ensure
232
- r.close
233
- w.close
234
- thread&.kill
269
+ end.value
235
270
  end
236
271
 
237
272
  private def pop_ready
@@ -255,6 +290,7 @@ module IO::Event
255
290
 
256
291
  readable = Array.new
257
292
  writable = Array.new
293
+ priority = Array.new
258
294
 
259
295
  @waiting.each do |io, waiter|
260
296
  waiter.each do |fiber, events|
@@ -265,12 +301,16 @@ module IO::Event
265
301
  if (events & IO::WRITABLE) > 0
266
302
  writable << io
267
303
  end
304
+
305
+ if (events & IO::PRIORITY) > 0
306
+ priority << io
307
+ end
268
308
  end
269
309
  end
270
310
 
271
311
  @blocked = true
272
312
  duration = 0 unless @ready.empty?
273
- readable, writable, _ = ::IO.select(readable, writable, nil, duration)
313
+ readable, writable, priority = ::IO.select(readable, writable, priority, duration)
274
314
  @blocked = false
275
315
 
276
316
  ready = Hash.new(0)
@@ -283,16 +323,16 @@ module IO::Event
283
323
  ready[io] |= IO::WRITABLE
284
324
  end
285
325
 
326
+ priority&.each do |io|
327
+ ready[io] |= IO::PRIORITY
328
+ end
329
+
286
330
  ready.each do |io, events|
287
331
  @waiting.delete(io).transfer(events)
288
332
  end
289
333
 
290
334
  return ready.size
291
335
  end
292
-
293
- private def blocking(&block)
294
- Fiber.new(blocking: true, &block).resume
295
- end
296
336
  end
297
337
  end
298
338
  end
@@ -1,25 +1,11 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021-2022, by Samuel Williams.
20
5
 
21
6
  require_relative 'selector/select'
22
7
  require_relative 'debug/selector'
8
+ require_relative 'support'
23
9
 
24
10
  module IO::Event
25
11
  module Selector
@@ -32,12 +18,14 @@ module IO::Event
32
18
  end
33
19
  end
34
20
 
35
- if self.const_defined?(:EPoll)
36
- return EPoll
21
+ if self.const_defined?(:URing)
22
+ URing
23
+ elsif self.const_defined?(:EPoll)
24
+ EPoll
37
25
  elsif self.const_defined?(:KQueue)
38
- return KQueue
26
+ KQueue
39
27
  else
40
- return Select
28
+ Select
41
29
  end
42
30
  end
43
31
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2022, by Samuel Williams.
5
+
6
+ class IO
7
+ module Event
8
+ module Support
9
+ def self.buffer?
10
+ IO.const_defined?(:Buffer)
11
+ end
12
+
13
+ def self.fiber_scheduler_v1?
14
+ IO.const_defined?(:Buffer) and !Fiber.respond_to?(:blocking)
15
+ end
16
+
17
+ def self.fiber_scheduler_v2?
18
+ IO.const_defined?(:Buffer) and Fiber.respond_to?(:blocking) and IO::Buffer.instance_method(:read).arity == -1
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,23 +1,10 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
20
2
 
21
- module IO::Event
22
- VERSION = "1.0.9"
3
+ # Released under the MIT License.
4
+ # Copyright, 2021-2022, by Samuel Williams.
5
+
6
+ class IO
7
+ module Event
8
+ VERSION = "1.1.0"
9
+ end
23
10
  end
data/lib/io/event.rb CHANGED
@@ -1,22 +1,7 @@
1
- # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining a copy
4
- # of this software and associated documentation files (the "Software"), to deal
5
- # in the Software without restriction, including without limitation the rights
6
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- # copies of the Software, and to permit persons to whom the Software is
8
- # furnished to do so, subject to the following conditions:
9
- #
10
- # The above copyright notice and this permission notice shall be included in
11
- # all copies or substantial portions of the Software.
12
- #
13
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- # THE SOFTWARE.
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2021, by Samuel Williams.
20
5
 
21
6
  require_relative 'event/version'
22
7
  require_relative 'event/selector'
data/license.md ADDED
@@ -0,0 +1,25 @@
1
+ # MIT License
2
+
3
+ Copyright, 2021-2022, by Samuel Williams.
4
+ Copyright, 2021, by Delton Ding.
5
+ Copyright, 2021, by Benoit Daloze.
6
+ Copyright, 2022, by Alex Matchneer.
7
+ Copyright, 2022, by Bruno Sutic.
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
data/readme.md ADDED
@@ -0,0 +1,23 @@
1
+ # ![Event](logo.svg)
2
+
3
+ Provides low level cross-platform primitives for constructing event loops, with support for `select`, `kqueue`, `epoll` and `io_uring`.
4
+
5
+ [![Development Status](https://github.com/socketry/io-event/workflows/Test/badge.svg)](https://github.com/socketry/io-event/actions?workflow=Test)
6
+
7
+ ## Motivation
8
+
9
+ The initial proof-of-concept [Async](https://github.com/socketry/async) was built on [NIO4r](https://github.com/socketry/nio4r). It was perfectly acceptable and well tested in production, however being built on `libev` was a little bit limiting. I wanted to directly built my fiber scheduler into the fabric of the event loop, which is what this gem exposes - it is specifically implemented to support building event loops beneath the fiber scheduler interface, providing an efficient C implementation of all the core operations.
10
+
11
+ ## Usage
12
+
13
+ Please see the [project documentation](https://socketry.github.io/io-event/).
14
+
15
+ ## Contributing
16
+
17
+ We welcome contributions to this project.
18
+
19
+ 1. Fork it
20
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
21
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
22
+ 4. Push to the branch (`git push origin my-new-feature`)
23
+ 5. Create new Pull Request
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: io-event
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -14,33 +14,34 @@ bindir: bin
14
14
  cert_chain:
15
15
  - |
16
16
  -----BEGIN CERTIFICATE-----
17
- MIIEhDCCAuygAwIBAgIBATANBgkqhkiG9w0BAQsFADA3MTUwMwYDVQQDDCxzYW11
18
- ZWwud2lsbGlhbXMvREM9b3Jpb250cmFuc2Zlci9EQz1jby9EQz1uejAeFw0yMTA4
19
- MTYwNjMzNDRaFw0yMjA4MTYwNjMzNDRaMDcxNTAzBgNVBAMMLHNhbXVlbC53aWxs
20
- aWFtcy9EQz1vcmlvbnRyYW5zZmVyL0RDPWNvL0RDPW56MIIBojANBgkqhkiG9w0B
21
- AQEFAAOCAY8AMIIBigKCAYEAyXLSS/cw+fXJ5e7hi+U/TeChPWeYdwJojDsFY1xr
22
- xvtqbTTL8gbLHz5LW3QD2nfwCv3qTlw0qI3Ie7a9VMJMbSvgVEGEfQirqIgJXWMj
23
- eNMDgKsMJtC7u/43abRKx7TCURW3iWyR19NRngsJJmaR51yGGGm2Kfsr+JtKKLtL
24
- L188Wm3f13KAx7QJU8qyuBnj1/gWem076hzdA7xi1DbrZrch9GCRz62xymJlrJHn
25
- 9iZEZ7AxrS7vokhMlzSr/XMUihx/8aFKtk+tMLClqxZSmBWIErWdicCGTULXCBNb
26
- E/mljo4zEVKhlTWpJklMIhr55ZRrSarKFuW7en0+tpJrfsYiAmXMJNi4XAYJH7uL
27
- rgJuJwSaa/dMz+VmUoo7VKtSfCoOI+6v5/z0sK3oT6sG6ZwyI47DBq2XqNC6tnAj
28
- w+XmCywiTQrFzMMAvcA7rPI4F0nU1rZId51rOvvfxaONp+wgTi4P8owZLw0/j0m4
29
- 8C20DYi6EYx4AHDXiLpElWh3AgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8E
30
- BAMCBLAwHQYDVR0OBBYEFB6ZaeWKxQjGTI+pmz7cKRmMIywwMC4GA1UdEQQnMCWB
31
- I3NhbXVlbC53aWxsaWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWB
32
- I3NhbXVlbC53aWxsaWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEB
33
- CwUAA4IBgQBVoM+pu3dpdUhZM1w051iw5GfiqclAr1Psypf16Tiod/ho//4oAu6T
34
- 9fj3DPX/acWV9P/FScvqo4Qgv6g4VWO5ZU7z2JmPoTXZtYMunRAmQPFL/gSUc6aK
35
- vszMHIyhtyzRc6DnfW2AiVOjMBjaYv8xXZc9bduniRVPrLR4J7ozmGLh4o4uJp7w
36
- x9KCFaR8Lvn/r0oJWJOqb/DMAYI83YeN2Dlt3jpwrsmsONrtC5S3gOUle5afSGos
37
- bYt5ocnEpKSomR9ZtnCGljds/aeO1Xgpn2r9HHcjwnH346iNrnHmMlC7BtHUFPDg
38
- Ts92S47PTOXzwPBDsrFiq3VLbRjHSwf8rpqybQBH9MfzxGGxTaETQYOd6b4e4Ag6
39
- y92abGna0bmIEb4+Tx9rQ10Uijh1POzvr/VTH4bbIPy9FbKrRsIQ24qDbNJRtOpE
40
- RAOsIl+HOBTb252nx1kIRN5hqQx272AJCbCjKx8egcUQKffFVVCI0nye09v5CK+a
41
- HiLJ8VOFx6w=
17
+ MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
18
+ ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
19
+ CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
20
+ MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
21
+ MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
22
+ bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
23
+ igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
24
+ 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
25
+ sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
26
+ e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
27
+ XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
28
+ RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
29
+ tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
30
+ zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
31
+ xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
32
+ BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
33
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
34
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
35
+ cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
36
+ xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
37
+ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
38
+ 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
39
+ JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
40
+ eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
41
+ Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
42
+ voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
43
  -----END CERTIFICATE-----
43
- date: 2022-05-03 00:00:00.000000000 Z
44
+ date: 2022-10-13 00:00:00.000000000 Z
44
45
  dependencies:
45
46
  - !ruby/object:Gem::Dependency
46
47
  name: bake
@@ -105,6 +106,7 @@ extensions:
105
106
  - ext/extconf.rb
106
107
  extra_rdoc_files: []
107
108
  files:
109
+ - design.md
108
110
  - ext/extconf.rb
109
111
  - ext/io/event/event.c
110
112
  - ext/io/event/event.h
@@ -124,7 +126,10 @@ files:
124
126
  - lib/io/event/interrupt.rb
125
127
  - lib/io/event/selector.rb
126
128
  - lib/io/event/selector/select.rb
129
+ - lib/io/event/support.rb
127
130
  - lib/io/event/version.rb
131
+ - license.md
132
+ - readme.md
128
133
  homepage: https://github.com/socketry/io-event
129
134
  licenses:
130
135
  - MIT
metadata.gz.sig CHANGED
Binary file