summaryrefslogtreecommitdiff
path: root/scheduler.c
diff options
context:
space:
mode:
Diffstat (limited to 'scheduler.c')
-rw-r--r--scheduler.c118
1 files changed, 85 insertions, 33 deletions
diff --git a/scheduler.c b/scheduler.c
index fb84e6b4dd..3159635dba 100644
--- a/scheduler.c
+++ b/scheduler.c
@@ -161,6 +161,21 @@ verify_interface(VALUE scheduler)
}
}
+static VALUE
+fiber_scheduler_close(VALUE scheduler)
+{
+ return rb_fiber_scheduler_close(scheduler);
+}
+
+static VALUE
+fiber_scheduler_close_ensure(VALUE _thread)
+{
+ rb_thread_t *thread = (rb_thread_t*)_thread;
+ thread->scheduler = Qnil;
+
+ return Qnil;
+}
+
VALUE
rb_fiber_scheduler_set(VALUE scheduler)
{
@@ -178,7 +193,8 @@ rb_fiber_scheduler_set(VALUE scheduler)
// That way, we do not need to consider interactions, e.g., of a Fiber from
// the previous scheduler with the new scheduler.
if (thread->scheduler != Qnil) {
- rb_fiber_scheduler_close(thread->scheduler);
+ // rb_fiber_scheduler_close(thread->scheduler);
+ rb_ensure(fiber_scheduler_close, thread->scheduler, fiber_scheduler_close_ensure, (VALUE)thread);
}
thread->scheduler = scheduler;
@@ -458,19 +474,18 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
/*
* Document-method: Fiber::Scheduler#io_read
- * call-seq: io_read(io, buffer, length) -> read length or -errno
+ * call-seq: io_read(io, buffer, length, offset) -> read length or -errno
*
- * Invoked by IO#read to read +length+ bytes from +io+ into a specified
- * +buffer+ (see IO::Buffer).
+ * Invoked by IO#read or IO#Buffer.read to read +length+ bytes from +io+ into a
+ * specified +buffer+ (see IO::Buffer) at the given +offset+.
*
- * 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.
+ * 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.
+ * 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
@@ -478,8 +493,8 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
*
* 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).
+ * 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_.
*/
@@ -493,13 +508,19 @@ rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t lengt
return rb_check_funcall(scheduler, id_io_read, 4, arguments);
}
-
/*
* Document-method: Fiber::Scheduler#io_read
* call-seq: io_pread(io, buffer, from, length, offset) -> read length or -errno
*
- * Invoked by IO::Buffer#pread. See that method for description of arguments.
+ * Invoked by IO#pread or IO::Buffer#pread to read +length+ bytes from +io+
+ * at offset +from+ into a specified +buffer+ (see IO::Buffer) at the given
+ * +offset+.
*
+ * This method is semantically the same as #io_read, but it allows to specify
+ * the offset to read from and is often better for asynchronous IO on the same
+ * file.
+ *
+ * The method should be considered _experimental_.
*/
VALUE
rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset)
@@ -513,28 +534,29 @@ rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buff
/*
* Document-method: Scheduler#io_write
- * call-seq: io_write(io, buffer, length) -> written length or -errno
+ * call-seq: io_write(io, buffer, length, offset) -> written length or -errno
*
- * Invoked by IO#write to write +length+ bytes to +io+ from
- * from a specified +buffer+ (see IO::Buffer).
+ * Invoked by IO#write or IO::Buffer#write to write +length+ bytes to +io+ from
+ * from a specified +buffer+ (see IO::Buffer) at the given +offset+.
*
- * 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.
+ * 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.
+ * 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.
+ * 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).
+ * 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_.
*/
@@ -552,7 +574,15 @@ rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t leng
* Document-method: Fiber::Scheduler#io_pwrite
* call-seq: io_pwrite(io, buffer, from, length, offset) -> written length or -errno
*
- * Invoked by IO::Buffer#pwrite. See that method for description of arguments.
+ * Invoked by IO#pwrite or IO::Buffer#pwrite to write +length+ bytes to +io+
+ * at offset +from+ into a specified +buffer+ (see IO::Buffer) at the given
+ * +offset+.
+ *
+ * This method is semantically the same as #io_write, but it allows to specify
+ * the offset to write to and is often better for asynchronous IO on the same
+ * file.
+ *
+ * The method should be considered _experimental_.
*
*/
VALUE
@@ -572,8 +602,7 @@ rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t
VALUE result = rb_fiber_scheduler_io_read(scheduler, io, buffer, length, 0);
- rb_io_buffer_unlock(buffer);
- rb_io_buffer_free(buffer);
+ rb_io_buffer_free_locked(buffer);
return result;
}
@@ -585,8 +614,31 @@ rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base,
VALUE result = rb_fiber_scheduler_io_write(scheduler, io, buffer, length, 0);
- rb_io_buffer_unlock(buffer);
- rb_io_buffer_free(buffer);
+ rb_io_buffer_free_locked(buffer);
+
+ return result;
+}
+
+VALUE
+rb_fiber_scheduler_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size, size_t length)
+{
+ VALUE buffer = rb_io_buffer_new(base, size, RB_IO_BUFFER_LOCKED);
+
+ VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, from, buffer, length, 0);
+
+ rb_io_buffer_free_locked(buffer);
+
+ return result;
+}
+
+VALUE
+rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size, size_t length)
+{
+ VALUE buffer = rb_io_buffer_new((void*)base, size, RB_IO_BUFFER_LOCKED|RB_IO_BUFFER_READONLY);
+
+ VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, from, buffer, length, 0);
+
+ rb_io_buffer_free_locked(buffer);
return result;
}