summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2020-08-21 00:53:08 +1200
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2020-09-14 16:44:09 +1200
commit701dcbb3ca9bf04b61cc07156608c61aaf9173f0 (patch)
tree4f732ba3b246c53a075894eb7e7758bb55e57607
parent132453fa521cf87693035769031f3501ddc02f4a (diff)
Add support for hooking `IO#read`.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3434
-rw-r--r--include/ruby/io.h2
-rw-r--r--internal/scheduler.h7
-rw-r--r--io.c6
-rw-r--r--scheduler.c18
4 files changed, 27 insertions, 6 deletions
diff --git a/include/ruby/io.h b/include/ruby/io.h
index fc6240adcc..19b2036a86 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -59,6 +59,8 @@ PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t {
typedef struct rb_io_buffer_t rb_io_buffer_t;
typedef struct rb_io_t {
+ VALUE self;
+
FILE *stdio_file; /* stdio ptr for read/write if available */
int fd; /* file descriptor */
int mode; /* mode flags: FMODE_XXXs */
diff --git a/internal/scheduler.h b/internal/scheduler.h
index be976d7be5..f5a41af064 100644
--- a/internal/scheduler.h
+++ b/internal/scheduler.h
@@ -21,7 +21,10 @@ VALUE rb_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeou
VALUE rb_scheduler_io_wait_readable(VALUE scheduler, VALUE io);
VALUE rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io);
-VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, VALUE offset, VALUE length);
-VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, VALUE offset, VALUE length);
+int rb_scheduler_supports_io_read(VALUE scheduler);
+VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
+
+int rb_scheduler_supports_io_write(VALUE scheduler);
+VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
#endif /* RUBY_SCHEDULER_H */
diff --git a/io.c b/io.c
index fbc913bad8..f73a508a0c 100644
--- a/io.c
+++ b/io.c
@@ -2619,6 +2619,11 @@ bufread_call(VALUE arg)
static long
io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
{
+ VALUE scheduler = rb_thread_current_scheduler();
+ if (scheduler != Qnil && rb_scheduler_supports_io_read(scheduler)) {
+ return rb_scheduler_io_read(scheduler, fptr->self, str, offset, size);
+ }
+
long len;
struct bufread_arg arg;
@@ -8511,6 +8516,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
fmode |= FMODE_PREP;
}
MakeOpenFile(io, fp);
+ fp->self = io;
fp->fd = fd;
fp->mode = fmode;
fp->encs = convconfig;
diff --git a/scheduler.c b/scheduler.c
index 4eaf12b333..9821d07636 100644
--- a/scheduler.c
+++ b/scheduler.c
@@ -59,13 +59,23 @@ VALUE rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
return rb_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), Qnil);
}
-VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, VALUE offset, VALUE length)
+int rb_scheduler_supports_io_read(VALUE scheduler)
{
- return rb_funcall(scheduler, id_io_read, 4, io, buffer, offset, length);
+ return rb_respond_to(scheduler, id_io_read);
}
-VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, VALUE offset, VALUE length)
+VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
+{
+ return rb_funcall(scheduler, id_io_read, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
+}
+
+int rb_scheduler_supports_io_write(VALUE scheduler)
+{
+ return rb_respond_to(scheduler, id_io_write);
+}
+
+VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
{
// We should ensure string has capacity to receive data, and then resize it afterwards.
- return rb_funcall(scheduler, id_io_write, 4, io, buffer, offset, length);
+ return rb_funcall(scheduler, id_io_write, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
}