io-event 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/design.md +63 -0
- data/ext/extconf.rb +4 -0
- data/ext/io/event/selector/epoll.c +44 -10
- data/ext/io/event/selector/kqueue.c +40 -10
- data/ext/io/event/selector/selector.h +4 -0
- data/ext/io/event/selector/uring.c +36 -11
- data/lib/io/event/debug/selector.rb +16 -27
- data/lib/io/event/interrupt.rb +4 -19
- data/lib/io/event/selector/select.rb +84 -44
- data/lib/io/event/selector.rb +11 -23
- data/lib/io/event/support.rb +22 -0
- data/lib/io/event/version.rb +8 -21
- data/lib/io/event.rb +4 -19
- data/license.md +25 -0
- data/readme.md +23 -0
- data.tar.gz.sig +0 -0
- metadata +39 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 529ab26d211811182c1ac8b7b292431533c830eddcfd8781185c9ea4ff623c93
|
4
|
+
data.tar.gz: cef3ea8d930d3f3f92e0c814c0f89405a78e3da1d4ebd6c0d1e73bd32f6839a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77cd0725f41f507e391f54dae4071c9b2721a1fc4ce1c4dbcbf7b4dac8a7453c0e4867679b9f9c615d82ce06af2b3f77745b0d1526f0c6bb02cf06a60c84f763
|
7
|
+
data.tar.gz: 6d9a389303af3b13540ff2761d8e35762e3af975c7e1defddf8765088129f43dc4584029947bafd2a6eb35c60f8206b0dc184d425c52163d1652392e62bb9333
|
checksums.yaml.gz.sig
ADDED
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
@@ -241,7 +241,7 @@ VALUE IO_Event_Selector_EPoll_process_wait(VALUE self, VALUE fiber, VALUE pid, V
|
|
241
241
|
rb_update_max_fd(process_wait_arguments.descriptor);
|
242
242
|
|
243
243
|
struct epoll_event event = {
|
244
|
-
.events = EPOLLIN|
|
244
|
+
.events = EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLONESHOT,
|
245
245
|
.data = {.ptr = (void*)fiber},
|
246
246
|
};
|
247
247
|
|
@@ -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
|
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
|
-
|
688
|
-
rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read,
|
689
|
-
rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write,
|
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
|
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
|
-
|
737
|
-
rb_define_method(IO_Event_Selector_KQueue, "
|
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
|
}
|
@@ -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, (
|
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
|
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
|
-
|
715
|
-
rb_define_method(IO_Event_Selector_URing, "
|
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
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
5
|
-
|
6
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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)
|
data/lib/io/event/interrupt.rb
CHANGED
@@ -1,22 +1,7 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
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
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
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
|
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
|
139
|
+
if Support.fiber_scheduler_v2?
|
152
140
|
EAGAIN = Errno::EAGAIN::Errno
|
153
141
|
|
154
|
-
def io_read(fiber, io, buffer, length)
|
155
|
-
|
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,
|
189
|
-
|
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
|
-
|
221
|
-
|
222
|
-
thread = Thread.new do
|
267
|
+
Thread.new do
|
223
268
|
Process::Status.wait(pid, flags)
|
224
|
-
|
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,
|
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
|
data/lib/io/event/selector.rb
CHANGED
@@ -1,25 +1,11 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
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?(:
|
36
|
-
|
21
|
+
if self.const_defined?(:URing)
|
22
|
+
URing
|
23
|
+
elsif self.const_defined?(:EPoll)
|
24
|
+
EPoll
|
37
25
|
elsif self.const_defined?(:KQueue)
|
38
|
-
|
26
|
+
KQueue
|
39
27
|
else
|
40
|
-
|
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
|
data/lib/io/event/version.rb
CHANGED
@@ -1,23 +1,10 @@
|
|
1
|
-
#
|
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
|
-
|
22
|
-
|
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
|
-
#
|
2
|
-
|
3
|
-
#
|
4
|
-
#
|
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
|
+
# 
|
2
|
+
|
3
|
+
Provides low level cross-platform primitives for constructing event loops, with support for `select`, `kqueue`, `epoll` and `io_uring`.
|
4
|
+
|
5
|
+
[](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
ADDED
Binary file
|
metadata
CHANGED
@@ -1,17 +1,47 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-event
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
-
-
|
8
|
+
- Bruno Sutic
|
9
9
|
- Benoit Daloze
|
10
10
|
- Delton Ding
|
11
|
+
- machty
|
11
12
|
autorequire:
|
12
13
|
bindir: bin
|
13
|
-
cert_chain:
|
14
|
-
|
14
|
+
cert_chain:
|
15
|
+
- |
|
16
|
+
-----BEGIN CERTIFICATE-----
|
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=
|
43
|
+
-----END CERTIFICATE-----
|
44
|
+
date: 2022-10-13 00:00:00.000000000 Z
|
15
45
|
dependencies:
|
16
46
|
- !ruby/object:Gem::Dependency
|
17
47
|
name: bake
|
@@ -76,6 +106,7 @@ extensions:
|
|
76
106
|
- ext/extconf.rb
|
77
107
|
extra_rdoc_files: []
|
78
108
|
files:
|
109
|
+
- design.md
|
79
110
|
- ext/extconf.rb
|
80
111
|
- ext/io/event/event.c
|
81
112
|
- ext/io/event/event.h
|
@@ -95,7 +126,10 @@ files:
|
|
95
126
|
- lib/io/event/interrupt.rb
|
96
127
|
- lib/io/event/selector.rb
|
97
128
|
- lib/io/event/selector/select.rb
|
129
|
+
- lib/io/event/support.rb
|
98
130
|
- lib/io/event/version.rb
|
131
|
+
- license.md
|
132
|
+
- readme.md
|
99
133
|
homepage: https://github.com/socketry/io-event
|
100
134
|
licenses:
|
101
135
|
- MIT
|
@@ -115,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
149
|
- !ruby/object:Gem::Version
|
116
150
|
version: '0'
|
117
151
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
152
|
+
rubygems_version: 3.3.7
|
119
153
|
signing_key:
|
120
154
|
specification_version: 4
|
121
155
|
summary: An event loop.
|
metadata.gz.sig
ADDED
Binary file
|