@@ -37,6 +37,7 @@ static ID id_io_close;
3737static ID id_address_resolve ;
3838
3939static ID id_blocking_operation_wait ;
40+ static ID id_fiber_interrupt ;
4041
4142static ID id_fiber_schedule ;
4243
@@ -116,6 +117,7 @@ Init_Fiber_Scheduler(void)
116117 id_address_resolve = rb_intern_const ("address_resolve" );
117118
118119 id_blocking_operation_wait = rb_intern_const ("blocking_operation_wait" );
120+ id_fiber_interrupt = rb_intern_const ("fiber_interrupt" );
119121
120122 id_fiber_schedule = rb_intern_const ("fiber" );
121123
@@ -442,10 +444,21 @@ rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
442444 * Expected to return the subset of events that are ready immediately.
443445 *
444446 */
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+
445454VALUE
446455rb_fiber_scheduler_io_wait (VALUE scheduler , VALUE io , VALUE events , VALUE timeout )
447456{
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 );
449462}
450463
451464VALUE
@@ -515,14 +528,25 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
515528 *
516529 * The method should be considered _experimental_.
517530 */
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+
518538VALUE
519539rb_fiber_scheduler_io_read (VALUE scheduler , VALUE io , VALUE buffer , size_t length , size_t offset )
520540{
541+ if (!rb_respond_to (scheduler , id_io_read )) {
542+ return RUBY_Qundef ;
543+ }
544+
521545 VALUE arguments [] = {
522- io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
546+ scheduler , io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
523547 };
524548
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 );
526550}
527551
528552/*
@@ -539,14 +563,25 @@ rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t lengt
539563 *
540564 * The method should be considered _experimental_.
541565 */
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+
542573VALUE
543574rb_fiber_scheduler_io_pread (VALUE scheduler , VALUE io , rb_off_t from , VALUE buffer , size_t length , size_t offset )
544575{
576+ if (!rb_respond_to (scheduler , id_io_pread )) {
577+ return RUBY_Qundef ;
578+ }
579+
545580 VALUE arguments [] = {
546- io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
581+ scheduler , io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
547582 };
548583
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 );
550585}
551586
552587/*
@@ -577,14 +612,25 @@ rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buff
577612 *
578613 * The method should be considered _experimental_.
579614 */
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+
580622VALUE
581623rb_fiber_scheduler_io_write (VALUE scheduler , VALUE io , VALUE buffer , size_t length , size_t offset )
582624{
625+ if (!rb_respond_to (scheduler , id_io_write )) {
626+ return RUBY_Qundef ;
627+ }
628+
583629 VALUE arguments [] = {
584- io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
630+ scheduler , io , buffer , SIZET2NUM (length ), SIZET2NUM (offset )
585631 };
586632
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 );
588634}
589635
590636/*
@@ -602,14 +648,25 @@ rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t leng
602648 * The method should be considered _experimental_.
603649 *
604650 */
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+
605658VALUE
606659rb_fiber_scheduler_io_pwrite (VALUE scheduler , VALUE io , rb_off_t from , VALUE buffer , size_t length , size_t offset )
607660{
661+ if (!rb_respond_to (scheduler , id_io_pwrite )) {
662+ return RUBY_Qundef ;
663+ }
664+
608665 VALUE arguments [] = {
609- io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
666+ scheduler , io , buffer , OFFT2NUM (from ), SIZET2NUM (length ), SIZET2NUM (offset )
610667 };
611668
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 );
613670}
614671
615672VALUE
@@ -766,6 +823,15 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
766823 return rb_check_funcall (scheduler , id_blocking_operation_wait , 1 , & proc );
767824}
768825
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+
769835/*
770836 * Document-method: Fiber::Scheduler#fiber
771837 * call-seq: fiber(&block)
0 commit comments