@@ -293,13 +293,15 @@ rb_fiber_scheduler_blocking_operation_new(void *(*function)(void *), void *data,
293293 *
294294 * Hook methods are:
295295 *
296- * * #io_wait, #io_read, #io_write, #io_pread, #io_pwrite, and #io_select, #io_close
296+ * * #io_wait, #io_read, #io_write, #io_pread, #io_pwrite #io_select, and #io_close
297297 * * #process_wait
298298 * * #kernel_sleep
299299 * * #timeout_after
300300 * * #address_resolve
301301 * * #block and #unblock
302302 * * #blocking_operation_wait
303+ * * #fiber_interrupt
304+ * * #yield
303305 * * (the list is expanded as Ruby developers make more methods having non-blocking calls)
304306 *
305307 * When not specified otherwise, the hook implementations are mandatory: if they are not
@@ -371,6 +373,9 @@ Init_Fiber_Scheduler(void)
371373 rb_define_method (rb_cFiberScheduler , "unblock" , rb_fiber_scheduler_unblock , 2 );
372374 rb_define_method (rb_cFiberScheduler , "fiber" , rb_fiber_scheduler_fiber , -2 );
373375 rb_define_method (rb_cFiberScheduler , "blocking_operation_wait" , rb_fiber_scheduler_blocking_operation_wait , -2 );
376+ rb_define_method (rb_cFiberScheduler , "yield" , rb_fiber_scheduler_yield , 0 );
377+ rb_define_method (rb_cFiberScheduler , "fiber_interrupt" , rb_fiber_scheduler_fiber_interrupt , 2 );
378+ rb_define_method (rb_cFiberScheduler , "io_close" , rb_fiber_scheduler_io_close , 1 );
374379#endif
375380}
376381
@@ -527,7 +532,7 @@ rb_fiber_scheduler_make_timeout(struct timeval *timeout)
527532 * Document-method: Fiber::Scheduler#kernel_sleep
528533 * call-seq: kernel_sleep(duration = nil)
529534 *
530- * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide
535+ * Invoked by Kernel#sleep and Thread:: Mutex#sleep and is expected to provide
531536 * an implementation of sleeping in a non-blocking way. Implementation might
532537 * register the current fiber in some list of "which fiber wait until what
533538 * moment", call Fiber.yield to pass control, and then in #close resume
@@ -586,7 +591,7 @@ rb_fiber_scheduler_yield(VALUE scheduler)
586591 * However, as a result of this design, if the +block+ does not invoke any
587592 * non-blocking operations, it will be impossible to interrupt it. If you
588593 * desire to provide predictable points for timeouts, consider adding
589- * + sleep(0)+ .
594+ * <tt> sleep(0)</tt> .
590595 *
591596 * If the block is executed successfully, its result will be returned.
592597 *
@@ -641,7 +646,7 @@ rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
641646 * Document-method: Fiber::Scheduler#block
642647 * call-seq: block(blocker, timeout = nil)
643648 *
644- * Invoked by methods like Thread.join, and by Mutex, to signify that current
649+ * Invoked by methods like Thread.join, and by Thread:: Mutex, to signify that current
645650 * Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has
646651 * elapsed.
647652 *
@@ -661,8 +666,8 @@ rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
661666 * Document-method: Fiber::Scheduler#unblock
662667 * call-seq: unblock(blocker, fiber)
663668 *
664- * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock
665- * calls #block and Mutex#unlock calls #unblock). The scheduler should use
669+ * Invoked to wake up Fiber previously blocked with #block (for example, Thread:: Mutex#lock
670+ * calls #block and Thread:: Mutex#unlock calls #unblock). The scheduler should use
666671 * the +fiber+ parameter to understand which fiber is unblocked.
667672 *
668673 * +blocker+ is what was awaited for, but it is informational only (for debugging
@@ -1021,6 +1026,14 @@ rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, co
10211026 return result ;
10221027}
10231028
1029+ /*
1030+ * Document-method: Fiber::Scheduler#io_close
1031+ * call-seq: io_close(fd)
1032+ *
1033+ * Invoked by Ruby's core methods to notify scheduler that the IO object is closed. Note that
1034+ * the method will receive an integer file descriptor of the closed object, not an object
1035+ * itself.
1036+ */
10241037VALUE
10251038rb_fiber_scheduler_io_close (VALUE scheduler , VALUE io )
10261039{
@@ -1076,7 +1089,8 @@ rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname)
10761089 * call-seq: blocking_operation_wait(blocking_operation)
10771090 *
10781091 * Invoked by Ruby's core methods to run a blocking operation in a non-blocking way.
1079- * The blocking_operation is a Fiber::Scheduler::BlockingOperation that encapsulates the blocking operation.
1092+ * The blocking_operation is an opaque object that encapsulates the blocking operation
1093+ * and responds to a <tt>#call</tt> method without any arguments.
10801094 *
10811095 * If the scheduler doesn't implement this method, or if the scheduler doesn't execute
10821096 * the blocking operation, Ruby will fall back to the non-scheduler implementation.
@@ -1118,6 +1132,15 @@ VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*functi
11181132 return result ;
11191133}
11201134
1135+ /*
1136+ * Document-method: Fiber::Scheduler#fiber_interrupt
1137+ * call-seq: fiber_interrupt(fiber, exception)
1138+ *
1139+ * Invoked by Ruby's core methods to notify the scheduler that the blocked fiber should be interrupted
1140+ * with an exception. For example, IO#close uses this method to interrupt fibers that are performing
1141+ * blocking IO operations.
1142+ *
1143+ */
11211144VALUE rb_fiber_scheduler_fiber_interrupt (VALUE scheduler , VALUE fiber , VALUE exception )
11221145{
11231146 VALUE arguments [] = {
0 commit comments