Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Fiber::SchedulerInterface#io_read and #io_write #5280

Merged
merged 3 commits into from Dec 20, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
122 changes: 121 additions & 1 deletion cont.c
Expand Up @@ -2919,9 +2919,11 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self)
*
* Hook methods are:
*
* * #io_wait
* * #io_wait, #io_read, and #io_write
* * #process_wait
* * #kernel_sleep
* * #timeout_after
* * #address_resolve
* * #block and #unblock
* * (the list is expanded as Ruby developers make more methods having non-blocking calls)
*
Expand Down Expand Up @@ -3002,6 +3004,70 @@ rb_fiber_scheduler_interface_io_wait(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#io_read
* call-seq: io_read(io, buffer, length) -> read length or -errno
*
* Invoked by IO#read to read +length+ bytes from +io+ into a specified
* +buffer+ (see IO::Buffer).
*
* The +length+ argument is the "minimum length to be read".
* If the IO buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to
* 8KiB might be read, but at least 1KiB will be.
* Generally, the only case where less data than +length+ will be read is if
* there is an error reading the data.
*
* Specifying a +length+ of 0 is valid and means try reading at least once
* and return any available data.
*
* Suggested implementation should try to read from +io+ in a non-blocking
* manner and call #io_wait if the +io+ is not ready (which will yield control
* to other fibers).
*
* See IO::Buffer for an interface available to return data.
*
* Expected to return number of bytes read, or, in case of an error, <tt>-errno</tt>
* (negated number corresponding to system's error code).
*
* The method should be considered _experimental_.
*/
static VALUE
rb_fiber_scheduler_interface_io_read(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#io_write
* call-seq: io_write(io, buffer, length) -> written length or -errno
*
* Invoked by IO#write to write +length+ bytes to +io+ from
* from a specified +buffer+ (see IO::Buffer).
*
* The +length+ argument is the "(minimum) length to be written".
* If the IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB),
* at most 8KiB will be written, but at least 1KiB will be.
* Generally, the only case where less data than +length+ will be written is if
* there is an error writing the data.
*
* Specifying a +length+ of 0 is valid and means try writing at least once,
* as much data as possible.
*
* Suggested implementation should try to write to +io+ in a non-blocking
* manner and call #io_wait if the +io+ is not ready (which will yield control
* to other fibers).
*
* See IO::Buffer for an interface available to get data from buffer efficiently.
*
* Expected to return number of bytes written, or, in case of an error, <tt>-errno</tt>
* (negated number corresponding to system's error code).
*
* The method should be considered _experimental_.
*/
static VALUE
rb_fiber_scheduler_interface_io_write(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#kernel_sleep
* call-seq: kernel_sleep(duration = nil)
Expand All @@ -3018,6 +3084,56 @@ rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#address_resolve
* call-seq: address_resolve(hostname) -> array_of_stings or nil
ioquatix marked this conversation as resolved.
Show resolved Hide resolved
*
* Invoked by Socket::getaddrinfo and is expected to provide hostname resolution
* in a non-blocking way.
ioquatix marked this conversation as resolved.
Show resolved Hide resolved
*
* The method is expected to return an array of strings corresponding to ip
* addresses the +hostname+ is resolved to, or +nil+ if it can not be resolved.
*
* The method support should be considered _experimental_.
*/
static VALUE
rb_fiber_scheduler_interface_address_resolve(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#address_resolve
ioquatix marked this conversation as resolved.
Show resolved Hide resolved
* call-seq: timeout_after(duration, exception_class, *exception_arguments, &block) -> result of block
*
* Limit the execution time of a given +block+ to the given +duration+ if
* possible. When a non-blocking operation causes the +block+'s execution time
* to exceed the specified +duration+, that non-blocking operation should be
* interrupted by raising the specified +exception_class+ constructed with the
* given +exception_arguments+.
*
* General execution timeouts are often considered risky. This implementation
* will only interrupt non-blocking operations. This is by design because it's
* expected that non-blocking operations can fail for a variety of
* unpredictable reasons, so applications should already be robust in handling
* these conditions.
*
* However, as a result of this design, if the +block+ does not invoke any
* non-blocking operations, it will be impossible to interrupt it. If you
* desire to provide predictable points for timeouts, consider adding
* +sleep(0)+.
*
* This hook is invoked by Timeout.timeout and can also be invoked directly by
* the scheduler.
*
* If the block is executed successfully, its result will be returned.
*
* The exception will typically be raised using Fiber#raise.
*/
static VALUE
rb_fiber_scheduler_interface_timeout_after(VALUE self)
{
}

/*
* Document-method: SchedulerInterface#block
* call-seq: block(blocker, timeout = nil)
Expand Down Expand Up @@ -3131,7 +3247,11 @@ Init_Cont(void)
rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_interface_close, 0);
rb_define_method(rb_cFiberScheduler, "process_wait", rb_fiber_scheduler_interface_process_wait, 0);
rb_define_method(rb_cFiberScheduler, "io_wait", rb_fiber_scheduler_interface_io_wait, 0);
rb_define_method(rb_cFiberScheduler, "io_read", rb_fiber_scheduler_interface_io_read, 0);
rb_define_method(rb_cFiberScheduler, "io_write", rb_fiber_scheduler_interface_io_write, 0);
rb_define_method(rb_cFiberScheduler, "kernel_sleep", rb_fiber_scheduler_interface_kernel_sleep, 0);
rb_define_method(rb_cFiberScheduler, "address_resolve", rb_fiber_scheduler_interface_address_resolve, 0);
rb_define_method(rb_cFiberScheduler, "timeout_after", rb_fiber_scheduler_interface_timeout_after, 0);
rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_interface_block, 0);
rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_interface_unblock, 0);
rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler_interface_fiber, 0);
Expand Down