aboutsummaryrefslogtreecommitdiffstats
path: root/scheduler.c
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2023-03-31 00:48:55 +1300
committerGitHub <noreply@github.com>2023-03-31 00:48:55 +1300
commit648870b5c577239b3274b0b48c82fb74910dfabf (patch)
treef944e0a1919bcb46537e1f3bd522beee9e72288c /scheduler.c
parent6f122965cf8704f019445faead58040e9be2effb (diff)
downloadruby-648870b5c577239b3274b0b48c82fb74910dfabf.tar.gz
Support `IO#pread` / `IO#pwrite` using fiber scheduler. (#7594)
* Skip test if non-blocking file IO is not supported.
Diffstat (limited to 'scheduler.c')
-rw-r--r--scheduler.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/scheduler.c b/scheduler.c
index 477f11c03c..866e53993f 100644
--- a/scheduler.c
+++ b/scheduler.c
@@ -458,15 +458,15 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
/*
* Document-method: Fiber::Scheduler#io_read
- * call-seq: io_read(io, buffer, minimum_length) -> read length or -errno
+ * call-seq: io_read(io, buffer, length) -> read length or -errno
*
* Invoked by IO#read or IO#Buffer.read to read +length+ bytes from +io+ into a
- * specified +buffer+ (see IO::Buffer).
+ * specified +buffer+ (see IO::Buffer) at the given +offset+.
*
- * The +minimum_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.
@@ -492,13 +492,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)
@@ -512,16 +518,16 @@ 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, minimum_length) -> written length or -errno
+ * call-seq: io_write(io, buffer, length) -> written length or -errno
*
* Invoked by IO#write or IO::Buffer#write to write +length+ bytes to +io+ from
- * from a specified +buffer+ (see IO::Buffer).
+ * from a specified +buffer+ (see IO::Buffer) at the given +offset+.
*
- * The +minimum_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 +minimum_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.
@@ -552,7 +558,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 +586,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 +598,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;
}