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)); }