@@ -37,6 +37,7 @@ static ID id_io_close;
37
37
static ID id_address_resolve ;
38
38
39
39
static ID id_blocking_operation_wait ;
40
+ static ID id_fiber_interrupt ;
40
41
41
42
static ID id_fiber_schedule ;
42
43
@@ -116,6 +117,7 @@ Init_Fiber_Scheduler(void)
116
117
id_address_resolve = rb_intern_const ("address_resolve" );
117
118
118
119
id_blocking_operation_wait = rb_intern_const ("blocking_operation_wait" );
120
+ id_fiber_interrupt = rb_intern_const ("fiber_interrupt" );
119
121
120
122
id_fiber_schedule = rb_intern_const ("fiber" );
121
123
@@ -442,10 +444,21 @@ rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
442
444
* Expected to return the subset of events that are ready immediately.
443
445
*
444
446
*/
447
+ static VALUE
448
+ fiber_scheduler_io_wait (VALUE _argument ) {
449
+ VALUE * arguments = (VALUE * )_argument ;
450
+
451
+ return rb_funcallv (arguments [0 ], id_io_wait , 3 , arguments + 1 );
452
+ }
453
+
445
454
VALUE
446
455
rb_fiber_scheduler_io_wait (VALUE scheduler , VALUE io , VALUE events , VALUE timeout )
447
456
{
448
- return rb_funcall (scheduler , id_io_wait , 3 , io , events , timeout );
457
+ VALUE arguments [] = {
458
+ scheduler , io , events , timeout
459
+ };
460
+
461
+ return rb_thread_io_interruptible_operation (io , fiber_scheduler_io_wait , (VALUE )& arguments );
449
462
}
450
463
451
464
VALUE
@@ -515,14 +528,25 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
515
528
*
516
529
* The method should be considered _experimental_.
517
530
*/
531
+ static VALUE
532
+ fiber_scheduler_io_read (VALUE _argument ) {
533
+ VALUE * arguments = (VALUE * )_argument ;
534
+
535
+ return rb_funcallv (arguments [0 ], id_io_read , 4 , arguments + 1 );
536
+ }
537
+
518
538
VALUE
519
539
rb_fiber_scheduler_io_read (VALUE scheduler , VALUE io , VALUE buffer , size_t length , size_t offset )
520
540
{
541
+ if (!rb_respond_to (scheduler , id_io_read )) {
542
+ return RUBY_Qundef ;
543
+ }
544
+
521
545
VALUE arguments [] = {
522
- io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
546
+ scheduler , io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
523
547
};
524
548
525
- return rb_check_funcall ( scheduler , id_io_read , 4 , arguments );
549
+ return rb_thread_io_interruptible_operation ( io , fiber_scheduler_io_read , ( VALUE ) & arguments );
526
550
}
527
551
528
552
/*
@@ -539,14 +563,25 @@ rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t lengt
539
563
*
540
564
* The method should be considered _experimental_.
541
565
*/
566
+ static VALUE
567
+ fiber_scheduler_io_pread (VALUE _argument ) {
568
+ VALUE * arguments = (VALUE * )_argument ;
569
+
570
+ return rb_funcallv (arguments [0 ], id_io_pread , 5 , arguments + 1 );
571
+ }
572
+
542
573
VALUE
543
574
rb_fiber_scheduler_io_pread (VALUE scheduler , VALUE io , rb_off_t from , VALUE buffer , size_t length , size_t offset )
544
575
{
576
+ if (!rb_respond_to (scheduler , id_io_pread )) {
577
+ return RUBY_Qundef ;
578
+ }
579
+
545
580
VALUE arguments [] = {
546
- io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
581
+ scheduler , io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
547
582
};
548
583
549
- return rb_check_funcall ( scheduler , id_io_pread , 5 , arguments );
584
+ return rb_thread_io_interruptible_operation ( io , fiber_scheduler_io_pread , ( VALUE ) & arguments );
550
585
}
551
586
552
587
/*
@@ -577,14 +612,25 @@ rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buff
577
612
*
578
613
* The method should be considered _experimental_.
579
614
*/
615
+ static VALUE
616
+ fiber_scheduler_io_write (VALUE _argument ) {
617
+ VALUE * arguments = (VALUE * )_argument ;
618
+
619
+ return rb_funcallv (arguments [0 ], id_io_write , 4 , arguments + 1 );
620
+ }
621
+
580
622
VALUE
581
623
rb_fiber_scheduler_io_write (VALUE scheduler , VALUE io , VALUE buffer , size_t length , size_t offset )
582
624
{
625
+ if (!rb_respond_to (scheduler , id_io_write )) {
626
+ return RUBY_Qundef ;
627
+ }
628
+
583
629
VALUE arguments [] = {
584
- io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
630
+ scheduler , io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
585
631
};
586
632
587
- return rb_check_funcall ( scheduler , id_io_write , 4 , arguments );
633
+ return rb_thread_io_interruptible_operation ( io , fiber_scheduler_io_write , ( VALUE ) & arguments );
588
634
}
589
635
590
636
/*
@@ -602,14 +648,25 @@ rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t leng
602
648
* The method should be considered _experimental_.
603
649
*
604
650
*/
651
+ static VALUE
652
+ fiber_scheduler_io_pwrite (VALUE _argument ) {
653
+ VALUE * arguments = (VALUE * )_argument ;
654
+
655
+ return rb_funcallv (arguments [0 ], id_io_pwrite , 5 , arguments + 1 );
656
+ }
657
+
605
658
VALUE
606
659
rb_fiber_scheduler_io_pwrite (VALUE scheduler , VALUE io , rb_off_t from , VALUE buffer , size_t length , size_t offset )
607
660
{
661
+ if (!rb_respond_to (scheduler , id_io_pwrite )) {
662
+ return RUBY_Qundef ;
663
+ }
664
+
608
665
VALUE arguments [] = {
609
- io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
666
+ scheduler , io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
610
667
};
611
668
612
- return rb_check_funcall ( scheduler , id_io_pwrite , 5 , arguments );
669
+ return rb_thread_io_interruptible_operation ( io , fiber_scheduler_io_pwrite , ( VALUE ) & arguments );
613
670
}
614
671
615
672
VALUE
@@ -766,6 +823,15 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
766
823
return rb_check_funcall (scheduler , id_blocking_operation_wait , 1 , & proc );
767
824
}
768
825
826
+ VALUE rb_fiber_scheduler_fiber_interrupt (VALUE scheduler , VALUE fiber , VALUE exception )
827
+ {
828
+ VALUE arguments [] = {
829
+ fiber , exception
830
+ };
831
+
832
+ return rb_check_funcall (scheduler , id_fiber_interrupt , 2 , arguments );
833
+ }
834
+
769
835
/*
770
836
* Document-method: Fiber::Scheduler#fiber
771
837
* call-seq: fiber(&block)
0 commit comments