io-event 1.19.4 → 1.20.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/context/getting-started.md +31 -5
- data/ext/io/event/selector/epoll.c +71 -12
- data/ext/io/event/selector/kqueue.c +71 -8
- data/ext/io/event/selector/selector.h +4 -0
- data/ext/io/event/selector/uring.c +296 -53
- data/ext/io/event/worker_pool.c +45 -34
- data/lib/io/event/debug/selector.rb +6 -6
- data/lib/io/event/selector/select.rb +93 -59
- data/lib/io/event/version.rb +1 -1
- data/readme.md +8 -8
- data/releases.md +8 -0
- data.tar.gz.sig +0 -0
- metadata +1 -1
- 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: 648484dee2c6698568b24073b4fcf90a32629dcfa2119c450df16cae77f52c49
|
|
4
|
+
data.tar.gz: 895241950306f5dbc0f1c0b31f6981ec78096c6f90160c018a56dccc6102b799
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff589133ec2d19d400c0c80daf0dc1cbf448005d26ca2c2df1d893c08371387cc12d37e8d1133379b17ed599cbe947197e0765e59c9c30c603802794283d9226
|
|
7
|
+
data.tar.gz: ec3c7a5d210053cf1e66d22eb4673c208184a044cb3b55404f34d645fcca0267711fe36ee12b7e8a7ef360d5ff6ed70a3da5ad0d64765406ec52ea2295119c40
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/context/getting-started.md
CHANGED
|
@@ -25,29 +25,55 @@ This example shows how to perform a blocking operation
|
|
|
25
25
|
require "fiber"
|
|
26
26
|
require "io/event"
|
|
27
27
|
|
|
28
|
+
# Create an I/O event selector controlled by the main Fiber.
|
|
28
29
|
selector = IO::Event::Selector.new(Fiber.current)
|
|
30
|
+
|
|
31
|
+
# input: read end, output: write end.
|
|
29
32
|
input, output = IO.pipe
|
|
30
33
|
|
|
31
34
|
writer = Fiber.new do
|
|
35
|
+
puts "[writer] Writing data"
|
|
36
|
+
|
|
32
37
|
output.write("Hello World")
|
|
33
38
|
output.close
|
|
34
39
|
end
|
|
35
40
|
|
|
36
41
|
reader = Fiber.new do
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
puts "[reader] No data available, waiting for input"
|
|
43
|
+
|
|
44
|
+
# Suspend this Fiber until the input becomes readable.
|
|
45
|
+
selector.io_wait(
|
|
46
|
+
Fiber.current,
|
|
47
|
+
input,
|
|
48
|
+
IO::READABLE
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Execution resumes here once the selector detects the event.
|
|
52
|
+
puts "[reader] Received: #{input.read.inspect}"
|
|
39
53
|
end
|
|
40
54
|
|
|
41
|
-
|
|
55
|
+
puts "[main] Transferring to reader fiber"
|
|
42
56
|
reader.transfer
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
puts "[main] Reader is waiting, but main can keep running"
|
|
59
|
+
|
|
60
|
+
puts "[main] Transferring to writer fiber"
|
|
45
61
|
writer.transfer
|
|
46
62
|
|
|
63
|
+
puts "[main] Checking for I/O events"
|
|
47
64
|
selector.select(1)
|
|
48
65
|
|
|
66
|
+
puts "[main] Done"
|
|
67
|
+
|
|
49
68
|
# Results in:
|
|
50
|
-
#
|
|
69
|
+
# [main] Transferring to reader fiber
|
|
70
|
+
# [reader] No data available, waiting for input
|
|
71
|
+
# [main] Reader is waiting, but main can keep running
|
|
72
|
+
# [main] Transferring to writer fiber
|
|
73
|
+
# [writer] Writing data
|
|
74
|
+
# [main] Checking for I/O events
|
|
75
|
+
# [reader] Received: "Hello World"
|
|
76
|
+
# [main] Done
|
|
51
77
|
```
|
|
52
78
|
|
|
53
79
|
## Debugging
|
|
@@ -593,9 +593,11 @@ VALUE IO_Event_Selector_EPoll_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE e
|
|
|
593
593
|
#ifdef HAVE_RUBY_IO_BUFFER_H
|
|
594
594
|
|
|
595
595
|
struct io_read_arguments {
|
|
596
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
596
597
|
VALUE self;
|
|
597
598
|
VALUE fiber;
|
|
598
599
|
VALUE io;
|
|
600
|
+
#endif
|
|
599
601
|
|
|
600
602
|
int flags;
|
|
601
603
|
|
|
@@ -605,14 +607,20 @@ struct io_read_arguments {
|
|
|
605
607
|
void *base;
|
|
606
608
|
size_t size;
|
|
607
609
|
|
|
610
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
608
611
|
// The minimum number of bytes requested by the caller.
|
|
609
612
|
size_t length;
|
|
613
|
+
#endif
|
|
610
614
|
};
|
|
611
615
|
|
|
612
616
|
static
|
|
613
617
|
VALUE io_read_loop(VALUE _arguments) {
|
|
614
618
|
struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
|
|
615
619
|
|
|
620
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
621
|
+
ssize_t result = read(arguments->descriptor, arguments->base, arguments->size);
|
|
622
|
+
return rb_fiber_scheduler_io_result(result, errno);
|
|
623
|
+
#else
|
|
616
624
|
size_t length = arguments->length;
|
|
617
625
|
size_t total = 0;
|
|
618
626
|
|
|
@@ -635,6 +643,7 @@ VALUE io_read_loop(VALUE _arguments) {
|
|
|
635
643
|
}
|
|
636
644
|
|
|
637
645
|
return rb_fiber_scheduler_io_result(total, 0);
|
|
646
|
+
#endif
|
|
638
647
|
}
|
|
639
648
|
|
|
640
649
|
static
|
|
@@ -646,14 +655,27 @@ VALUE io_read_ensure(VALUE _arguments) {
|
|
|
646
655
|
return Qnil;
|
|
647
656
|
}
|
|
648
657
|
|
|
649
|
-
VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE
|
|
650
|
-
size_t offset = NUM2SIZET(_offset);
|
|
651
|
-
size_t length = NUM2SIZET(_length);
|
|
652
|
-
|
|
658
|
+
VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _first, VALUE _second) {
|
|
653
659
|
void *base;
|
|
654
660
|
size_t size;
|
|
655
661
|
rb_io_buffer_get_bytes_for_writing(buffer, &base, &size);
|
|
656
662
|
|
|
663
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
664
|
+
size_t offset = NUM2SIZET(_first);
|
|
665
|
+
size_t length = NUM2SIZET(_second);
|
|
666
|
+
|
|
667
|
+
if (!IO_Event_Selector_valid_buffer_range(size, offset, length)) {
|
|
668
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
669
|
+
} else if (length == 0) {
|
|
670
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
base = (char*)base + offset;
|
|
674
|
+
size = length;
|
|
675
|
+
#else
|
|
676
|
+
size_t length = NUM2SIZET(_first);
|
|
677
|
+
size_t offset = NUM2SIZET(_second);
|
|
678
|
+
|
|
657
679
|
if (offset > size) {
|
|
658
680
|
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
659
681
|
} else if (offset == size) {
|
|
@@ -662,19 +684,24 @@ VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
|
|
|
662
684
|
|
|
663
685
|
base = (char*)base + offset;
|
|
664
686
|
size -= offset;
|
|
687
|
+
#endif
|
|
665
688
|
|
|
666
689
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
|
667
690
|
|
|
668
691
|
struct io_read_arguments io_read_arguments = {
|
|
692
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
669
693
|
.self = self,
|
|
670
694
|
.fiber = fiber,
|
|
671
695
|
.io = io,
|
|
696
|
+
#endif
|
|
672
697
|
|
|
673
698
|
.flags = IO_Event_Selector_nonblock_set(descriptor),
|
|
674
699
|
.descriptor = descriptor,
|
|
675
700
|
.base = base,
|
|
676
701
|
.size = size,
|
|
702
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
677
703
|
.length = length,
|
|
704
|
+
#endif
|
|
678
705
|
};
|
|
679
706
|
|
|
680
707
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
|
@@ -682,6 +709,7 @@ VALUE IO_Event_Selector_EPoll_io_read(VALUE self, VALUE fiber, VALUE io, VALUE b
|
|
|
682
709
|
return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
|
|
683
710
|
}
|
|
684
711
|
|
|
712
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
685
713
|
VALUE IO_Event_Selector_EPoll_io_read_compatible(int argc, VALUE *argv, VALUE self)
|
|
686
714
|
{
|
|
687
715
|
rb_check_arity(argc, 4, 5);
|
|
@@ -694,11 +722,14 @@ VALUE IO_Event_Selector_EPoll_io_read_compatible(int argc, VALUE *argv, VALUE se
|
|
|
694
722
|
|
|
695
723
|
return IO_Event_Selector_EPoll_io_read(self, argv[0], argv[1], argv[2], argv[3], _offset);
|
|
696
724
|
}
|
|
725
|
+
#endif
|
|
697
726
|
|
|
698
727
|
struct io_write_arguments {
|
|
728
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
699
729
|
VALUE self;
|
|
700
730
|
VALUE fiber;
|
|
701
731
|
VALUE io;
|
|
732
|
+
#endif
|
|
702
733
|
|
|
703
734
|
int flags;
|
|
704
735
|
|
|
@@ -708,14 +739,20 @@ struct io_write_arguments {
|
|
|
708
739
|
const void *base;
|
|
709
740
|
size_t size;
|
|
710
741
|
|
|
742
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
711
743
|
// The minimum number of bytes requested by the caller.
|
|
712
744
|
size_t length;
|
|
745
|
+
#endif
|
|
713
746
|
};
|
|
714
747
|
|
|
715
748
|
static
|
|
716
749
|
VALUE io_write_loop(VALUE _arguments) {
|
|
717
750
|
struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
|
|
718
751
|
|
|
752
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
753
|
+
ssize_t result = write(arguments->descriptor, arguments->base, arguments->size);
|
|
754
|
+
return rb_fiber_scheduler_io_result(result, errno);
|
|
755
|
+
#else
|
|
719
756
|
size_t length = arguments->length;
|
|
720
757
|
size_t total = 0;
|
|
721
758
|
|
|
@@ -738,6 +775,7 @@ VALUE io_write_loop(VALUE _arguments) {
|
|
|
738
775
|
}
|
|
739
776
|
|
|
740
777
|
return rb_fiber_scheduler_io_result(total, 0);
|
|
778
|
+
#endif
|
|
741
779
|
};
|
|
742
780
|
|
|
743
781
|
static
|
|
@@ -749,14 +787,27 @@ VALUE io_write_ensure(VALUE _arguments) {
|
|
|
749
787
|
return Qnil;
|
|
750
788
|
};
|
|
751
789
|
|
|
752
|
-
VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE
|
|
753
|
-
size_t length = NUM2SIZET(_length);
|
|
754
|
-
size_t offset = NUM2SIZET(_offset);
|
|
755
|
-
|
|
790
|
+
VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _first, VALUE _second) {
|
|
756
791
|
const void *base;
|
|
757
792
|
size_t size;
|
|
758
793
|
rb_io_buffer_get_bytes_for_reading(buffer, &base, &size);
|
|
759
794
|
|
|
795
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
796
|
+
size_t offset = NUM2SIZET(_first);
|
|
797
|
+
size_t length = NUM2SIZET(_second);
|
|
798
|
+
|
|
799
|
+
if (!IO_Event_Selector_valid_buffer_range(size, offset, length)) {
|
|
800
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
801
|
+
} else if (length == 0) {
|
|
802
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
base = (const char*)base + offset;
|
|
806
|
+
size = length;
|
|
807
|
+
#else
|
|
808
|
+
size_t length = NUM2SIZET(_first);
|
|
809
|
+
size_t offset = NUM2SIZET(_second);
|
|
810
|
+
|
|
760
811
|
if (length > size) {
|
|
761
812
|
rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
|
|
762
813
|
}
|
|
@@ -769,19 +820,24 @@ VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
769
820
|
|
|
770
821
|
base = (const char*)base + offset;
|
|
771
822
|
size -= offset;
|
|
823
|
+
#endif
|
|
772
824
|
|
|
773
825
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
|
774
826
|
|
|
775
827
|
struct io_write_arguments io_write_arguments = {
|
|
828
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
776
829
|
.self = self,
|
|
777
830
|
.fiber = fiber,
|
|
778
831
|
.io = io,
|
|
832
|
+
#endif
|
|
779
833
|
|
|
780
834
|
.flags = IO_Event_Selector_nonblock_set(descriptor),
|
|
781
835
|
.descriptor = descriptor,
|
|
782
836
|
.base = base,
|
|
783
837
|
.size = size,
|
|
838
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
784
839
|
.length = length,
|
|
840
|
+
#endif
|
|
785
841
|
};
|
|
786
842
|
|
|
787
843
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
|
@@ -789,6 +845,7 @@ VALUE IO_Event_Selector_EPoll_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
789
845
|
return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
|
|
790
846
|
}
|
|
791
847
|
|
|
848
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
792
849
|
VALUE IO_Event_Selector_EPoll_io_write_compatible(int argc, VALUE *argv, VALUE self)
|
|
793
850
|
{
|
|
794
851
|
rb_check_arity(argc, 4, 5);
|
|
@@ -801,6 +858,7 @@ VALUE IO_Event_Selector_EPoll_io_write_compatible(int argc, VALUE *argv, VALUE s
|
|
|
801
858
|
|
|
802
859
|
return IO_Event_Selector_EPoll_io_write(self, argv[0], argv[1], argv[2], argv[3], _offset);
|
|
803
860
|
}
|
|
861
|
+
#endif
|
|
804
862
|
|
|
805
863
|
#endif
|
|
806
864
|
|
|
@@ -1123,13 +1181,14 @@ void Init_IO_Event_Selector_EPoll(VALUE IO_Event_Selector) {
|
|
|
1123
1181
|
rb_define_method(IO_Event_Selector_EPoll, "io_wait", IO_Event_Selector_EPoll_io_wait, 3);
|
|
1124
1182
|
|
|
1125
1183
|
#ifdef HAVE_RUBY_IO_BUFFER_H
|
|
1184
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
1185
|
+
rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read, 5);
|
|
1186
|
+
rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write, 5);
|
|
1187
|
+
#else
|
|
1126
1188
|
rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read_compatible, -1);
|
|
1127
1189
|
rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write_compatible, -1);
|
|
1128
1190
|
#endif
|
|
1129
|
-
|
|
1130
|
-
// Once compatibility isn't a concern, we can do this:
|
|
1131
|
-
// rb_define_method(IO_Event_Selector_EPoll, "io_read", IO_Event_Selector_EPoll_io_read, 5);
|
|
1132
|
-
// rb_define_method(IO_Event_Selector_EPoll, "io_write", IO_Event_Selector_EPoll_io_write, 5);
|
|
1191
|
+
#endif
|
|
1133
1192
|
|
|
1134
1193
|
rb_define_method(IO_Event_Selector_EPoll, "process_wait", IO_Event_Selector_EPoll_process_wait, 3);
|
|
1135
1194
|
}
|
|
@@ -582,9 +582,11 @@ VALUE IO_Event_Selector_KQueue_io_wait(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
582
582
|
#ifdef HAVE_RUBY_IO_BUFFER_H
|
|
583
583
|
|
|
584
584
|
struct io_read_arguments {
|
|
585
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
585
586
|
VALUE self;
|
|
586
587
|
VALUE fiber;
|
|
587
588
|
VALUE io;
|
|
589
|
+
#endif
|
|
588
590
|
|
|
589
591
|
int flags;
|
|
590
592
|
|
|
@@ -594,14 +596,20 @@ struct io_read_arguments {
|
|
|
594
596
|
void *base;
|
|
595
597
|
size_t size;
|
|
596
598
|
|
|
599
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
597
600
|
// The minimum number of bytes requested by the caller.
|
|
598
601
|
size_t length;
|
|
602
|
+
#endif
|
|
599
603
|
};
|
|
600
604
|
|
|
601
605
|
static
|
|
602
606
|
VALUE io_read_loop(VALUE _arguments) {
|
|
603
607
|
struct io_read_arguments *arguments = (struct io_read_arguments *)_arguments;
|
|
604
608
|
|
|
609
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
610
|
+
ssize_t result = read(arguments->descriptor, arguments->base, arguments->size);
|
|
611
|
+
return rb_fiber_scheduler_io_result(result, errno);
|
|
612
|
+
#else
|
|
605
613
|
size_t length = arguments->length;
|
|
606
614
|
size_t total = 0;
|
|
607
615
|
|
|
@@ -631,6 +639,7 @@ VALUE io_read_loop(VALUE _arguments) {
|
|
|
631
639
|
|
|
632
640
|
if (DEBUG_IO_READ) fprintf(stderr, "io_read_loop(fd=%d, length=%zu) -> %zu\n", arguments->descriptor, length, total);
|
|
633
641
|
return rb_fiber_scheduler_io_result(total, 0);
|
|
642
|
+
#endif
|
|
634
643
|
}
|
|
635
644
|
|
|
636
645
|
static
|
|
@@ -642,17 +651,30 @@ VALUE io_read_ensure(VALUE _arguments) {
|
|
|
642
651
|
return Qnil;
|
|
643
652
|
}
|
|
644
653
|
|
|
645
|
-
VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE
|
|
654
|
+
VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _first, VALUE _second) {
|
|
646
655
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
|
647
656
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
|
648
657
|
|
|
649
|
-
size_t length = NUM2SIZET(_length);
|
|
650
|
-
size_t offset = NUM2SIZET(_offset);
|
|
651
|
-
|
|
652
658
|
void *base;
|
|
653
659
|
size_t size;
|
|
654
660
|
rb_io_buffer_get_bytes_for_writing(buffer, &base, &size);
|
|
655
661
|
|
|
662
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
663
|
+
size_t offset = NUM2SIZET(_first);
|
|
664
|
+
size_t length = NUM2SIZET(_second);
|
|
665
|
+
|
|
666
|
+
if (!IO_Event_Selector_valid_buffer_range(size, offset, length)) {
|
|
667
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
668
|
+
} else if (length == 0) {
|
|
669
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
base = (char*)base + offset;
|
|
673
|
+
size = length;
|
|
674
|
+
#else
|
|
675
|
+
size_t length = NUM2SIZET(_first);
|
|
676
|
+
size_t offset = NUM2SIZET(_second);
|
|
677
|
+
|
|
656
678
|
if (offset > size) {
|
|
657
679
|
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
658
680
|
} else if (offset == size) {
|
|
@@ -661,19 +683,24 @@ VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
661
683
|
|
|
662
684
|
base = (char*)base + offset;
|
|
663
685
|
size -= offset;
|
|
686
|
+
#endif
|
|
664
687
|
|
|
665
688
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
|
666
689
|
|
|
667
690
|
struct io_read_arguments io_read_arguments = {
|
|
691
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
668
692
|
.self = self,
|
|
669
693
|
.fiber = fiber,
|
|
670
694
|
.io = io,
|
|
695
|
+
#endif
|
|
671
696
|
|
|
672
697
|
.flags = IO_Event_Selector_nonblock_set(descriptor),
|
|
673
698
|
.descriptor = descriptor,
|
|
674
699
|
.base = base,
|
|
675
700
|
.size = size,
|
|
701
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
676
702
|
.length = length,
|
|
703
|
+
#endif
|
|
677
704
|
};
|
|
678
705
|
|
|
679
706
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
|
@@ -681,6 +708,7 @@ VALUE IO_Event_Selector_KQueue_io_read(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
681
708
|
return rb_ensure(io_read_loop, (VALUE)&io_read_arguments, io_read_ensure, (VALUE)&io_read_arguments);
|
|
682
709
|
}
|
|
683
710
|
|
|
711
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
684
712
|
static VALUE IO_Event_Selector_KQueue_io_read_compatible(int argc, VALUE *argv, VALUE self)
|
|
685
713
|
{
|
|
686
714
|
rb_check_arity(argc, 4, 5);
|
|
@@ -693,11 +721,14 @@ static VALUE IO_Event_Selector_KQueue_io_read_compatible(int argc, VALUE *argv,
|
|
|
693
721
|
|
|
694
722
|
return IO_Event_Selector_KQueue_io_read(self, argv[0], argv[1], argv[2], argv[3], _offset);
|
|
695
723
|
}
|
|
724
|
+
#endif
|
|
696
725
|
|
|
697
726
|
struct io_write_arguments {
|
|
727
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
698
728
|
VALUE self;
|
|
699
729
|
VALUE fiber;
|
|
700
730
|
VALUE io;
|
|
731
|
+
#endif
|
|
701
732
|
|
|
702
733
|
int flags;
|
|
703
734
|
|
|
@@ -707,14 +738,20 @@ struct io_write_arguments {
|
|
|
707
738
|
const void *base;
|
|
708
739
|
size_t size;
|
|
709
740
|
|
|
741
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
710
742
|
// The minimum number of bytes requested by the caller.
|
|
711
743
|
size_t length;
|
|
744
|
+
#endif
|
|
712
745
|
};
|
|
713
746
|
|
|
714
747
|
static
|
|
715
748
|
VALUE io_write_loop(VALUE _arguments) {
|
|
716
749
|
struct io_write_arguments *arguments = (struct io_write_arguments *)_arguments;
|
|
717
750
|
|
|
751
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
752
|
+
ssize_t result = write(arguments->descriptor, arguments->base, arguments->size);
|
|
753
|
+
return rb_fiber_scheduler_io_result(result, errno);
|
|
754
|
+
#else
|
|
718
755
|
size_t length = arguments->length;
|
|
719
756
|
size_t total = 0;
|
|
720
757
|
|
|
@@ -744,6 +781,7 @@ VALUE io_write_loop(VALUE _arguments) {
|
|
|
744
781
|
|
|
745
782
|
if (DEBUG_IO_WRITE) fprintf(stderr, "io_write_loop(fd=%d, length=%zu) -> %zu\n", arguments->descriptor, length, total);
|
|
746
783
|
return rb_fiber_scheduler_io_result(total, 0);
|
|
784
|
+
#endif
|
|
747
785
|
};
|
|
748
786
|
|
|
749
787
|
static
|
|
@@ -755,17 +793,30 @@ VALUE io_write_ensure(VALUE _arguments) {
|
|
|
755
793
|
return Qnil;
|
|
756
794
|
};
|
|
757
795
|
|
|
758
|
-
VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE
|
|
796
|
+
VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE buffer, VALUE _first, VALUE _second) {
|
|
759
797
|
struct IO_Event_Selector_KQueue *selector = NULL;
|
|
760
798
|
TypedData_Get_Struct(self, struct IO_Event_Selector_KQueue, &IO_Event_Selector_KQueue_Type, selector);
|
|
761
799
|
|
|
762
|
-
size_t length = NUM2SIZET(_length);
|
|
763
|
-
size_t offset = NUM2SIZET(_offset);
|
|
764
|
-
|
|
765
800
|
const void *base;
|
|
766
801
|
size_t size;
|
|
767
802
|
rb_io_buffer_get_bytes_for_reading(buffer, &base, &size);
|
|
768
803
|
|
|
804
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
805
|
+
size_t offset = NUM2SIZET(_first);
|
|
806
|
+
size_t length = NUM2SIZET(_second);
|
|
807
|
+
|
|
808
|
+
if (!IO_Event_Selector_valid_buffer_range(size, offset, length)) {
|
|
809
|
+
return rb_fiber_scheduler_io_result(-1, EINVAL);
|
|
810
|
+
} else if (length == 0) {
|
|
811
|
+
return rb_fiber_scheduler_io_result(0, 0);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
base = (const char*)base + offset;
|
|
815
|
+
size = length;
|
|
816
|
+
#else
|
|
817
|
+
size_t length = NUM2SIZET(_first);
|
|
818
|
+
size_t offset = NUM2SIZET(_second);
|
|
819
|
+
|
|
769
820
|
if (length > size) {
|
|
770
821
|
rb_raise(rb_eRuntimeError, "Length exceeds size of buffer!");
|
|
771
822
|
}
|
|
@@ -778,19 +829,24 @@ VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
778
829
|
|
|
779
830
|
base = (const char*)base + offset;
|
|
780
831
|
size -= offset;
|
|
832
|
+
#endif
|
|
781
833
|
|
|
782
834
|
int descriptor = IO_Event_Selector_io_descriptor(io);
|
|
783
835
|
|
|
784
836
|
struct io_write_arguments io_write_arguments = {
|
|
837
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
785
838
|
.self = self,
|
|
786
839
|
.fiber = fiber,
|
|
787
840
|
.io = io,
|
|
841
|
+
#endif
|
|
788
842
|
|
|
789
843
|
.flags = IO_Event_Selector_nonblock_set(descriptor),
|
|
790
844
|
.descriptor = descriptor,
|
|
791
845
|
.base = base,
|
|
792
846
|
.size = size,
|
|
847
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
793
848
|
.length = length,
|
|
849
|
+
#endif
|
|
794
850
|
};
|
|
795
851
|
|
|
796
852
|
RB_OBJ_WRITTEN(self, Qundef, fiber);
|
|
@@ -798,6 +854,7 @@ VALUE IO_Event_Selector_KQueue_io_write(VALUE self, VALUE fiber, VALUE io, VALUE
|
|
|
798
854
|
return rb_ensure(io_write_loop, (VALUE)&io_write_arguments, io_write_ensure, (VALUE)&io_write_arguments);
|
|
799
855
|
}
|
|
800
856
|
|
|
857
|
+
#if RUBY_FIBER_SCHEDULER_VERSION < 4
|
|
801
858
|
static VALUE IO_Event_Selector_KQueue_io_write_compatible(int argc, VALUE *argv, VALUE self)
|
|
802
859
|
{
|
|
803
860
|
rb_check_arity(argc, 4, 5);
|
|
@@ -810,6 +867,7 @@ static VALUE IO_Event_Selector_KQueue_io_write_compatible(int argc, VALUE *argv,
|
|
|
810
867
|
|
|
811
868
|
return IO_Event_Selector_KQueue_io_write(self, argv[0], argv[1], argv[2], argv[3], _offset);
|
|
812
869
|
}
|
|
870
|
+
#endif
|
|
813
871
|
|
|
814
872
|
#endif
|
|
815
873
|
|
|
@@ -1125,8 +1183,13 @@ void Init_IO_Event_Selector_KQueue(VALUE IO_Event_Selector) {
|
|
|
1125
1183
|
rb_define_method(IO_Event_Selector_KQueue, "io_wait", IO_Event_Selector_KQueue_io_wait, 3);
|
|
1126
1184
|
|
|
1127
1185
|
#ifdef HAVE_RUBY_IO_BUFFER_H
|
|
1186
|
+
#if RUBY_FIBER_SCHEDULER_VERSION >= 4
|
|
1187
|
+
rb_define_method(IO_Event_Selector_KQueue, "io_read", IO_Event_Selector_KQueue_io_read, 5);
|
|
1188
|
+
rb_define_method(IO_Event_Selector_KQueue, "io_write", IO_Event_Selector_KQueue_io_write, 5);
|
|
1189
|
+
#else
|
|
1128
1190
|
rb_define_method(IO_Event_Selector_KQueue, "io_read", IO_Event_Selector_KQueue_io_read_compatible, -1);
|
|
1129
1191
|
rb_define_method(IO_Event_Selector_KQueue, "io_write", IO_Event_Selector_KQueue_io_write_compatible, -1);
|
|
1192
|
+
#endif
|
|
1130
1193
|
#endif
|
|
1131
1194
|
|
|
1132
1195
|
rb_define_method(IO_Event_Selector_KQueue, "process_wait", IO_Event_Selector_KQueue_process_wait, 3);
|
|
@@ -40,6 +40,10 @@ static inline int IO_Event_try_again(int error) {
|
|
|
40
40
|
return error == EAGAIN || error == EWOULDBLOCK;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
static inline int IO_Event_Selector_valid_buffer_range(size_t size, size_t offset, size_t length) {
|
|
44
|
+
return offset <= size && length <= size - offset;
|
|
45
|
+
}
|
|
46
|
+
|
|
43
47
|
// Enter a blocking region without the GVL. On Rubies without
|
|
44
48
|
// `RB_NOGVL_PENDING_INTR_FAIL`, refresh pending-interrupt state immediately
|
|
45
49
|
// before releasing the GVL so a signal cannot be stranded in the queue.
|