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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d72eba7de108f1051424997dec0f1d83a38a7a4d927089e1ca7ba0478922ef5
4
- data.tar.gz: 0a423df73be6c4aec9efc892014b867807794989b45500700a5bbca423ff8915
3
+ metadata.gz: 648484dee2c6698568b24073b4fcf90a32629dcfa2119c450df16cae77f52c49
4
+ data.tar.gz: 895241950306f5dbc0f1c0b31f6981ec78096c6f90160c018a56dccc6102b799
5
5
  SHA512:
6
- metadata.gz: cc15fd5deeaf2aeb9fcad4d58da2e06daf6e9ec6933020ccc2bfb1ad3705e52f52958b5086e459cc4a85c0a5ee22c16482b7cd9d3a0e0ff254f725df72bcc02e
7
- data.tar.gz: 7fcab614752bb5db345e31e60a34d52e9b06d1386ac6531b301063ae77a1dd01cc1f5b2beeb5e482a89f4898ca9c85ce4cc56faf4db37219e3fd9c2478266118
6
+ metadata.gz: ff589133ec2d19d400c0c80daf0dc1cbf448005d26ca2c2df1d893c08371387cc12d37e8d1133379b17ed599cbe947197e0765e59c9c30c603802794283d9226
7
+ data.tar.gz: ec3c7a5d210053cf1e66d22eb4673c208184a044cb3b55404f34d645fcca0267711fe36ee12b7e8a7ef360d5ff6ed70a3da5ad0d64765406ec52ea2295119c40
checksums.yaml.gz.sig CHANGED
Binary file
@@ -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
- selector.io_wait(Fiber.current, input, IO::READABLE)
38
- pp read: input.read
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
- # The reader will be blocked until the IO has data available:
55
+ puts "[main] Transferring to reader fiber"
42
56
  reader.transfer
43
57
 
44
- # Write some data to the pipe and close the writing end:
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
- # {:read=>"Hello World"}
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 _length, VALUE _offset) {
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 _length, VALUE _offset) {
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 _length, VALUE _offset) {
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 _length, VALUE _offset) {
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.