Feature #11339 ยป 0001-io.c-avoid-kwarg-parsing-in-C-API.patch
| benchmark/bm_io_nonblock_noex2.rb | ||
|---|---|---|
|
nr = 1_000_000
|
||
|
i = 0
|
||
|
msg = '.'
|
||
|
buf = '.'
|
||
|
begin
|
||
|
r, w = IO.pipe
|
||
|
while i < nr
|
||
|
i += 1
|
||
|
w.write_nonblock(msg, exception: false)
|
||
|
r.read_nonblock(1, buf, exception: false)
|
||
|
end
|
||
|
rescue ArgumentError # old Rubies
|
||
|
while i < nr
|
||
|
i += 1
|
||
|
w.write_nonblock(msg)
|
||
|
r.read_nonblock(1, buf)
|
||
|
end
|
||
|
ensure
|
||
|
r.close
|
||
|
w.close
|
||
|
end
|
||
| io.c | ||
|---|---|---|
|
*/
|
||
|
static VALUE
|
||
|
io_read_nonblock(int argc, VALUE *argv, VALUE io)
|
||
|
{
|
||
|
VALUE ret, opts;
|
||
|
rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
|
||
|
ret = io_getpartial(argc, argv, io, opts, 1);
|
||
|
if (NIL_P(ret)) {
|
||
|
if (no_exception_p(opts))
|
||
|
return Qnil;
|
||
|
else
|
||
|
rb_eof_error();
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
static VALUE
|
||
|
io_write_nonblock(VALUE io, VALUE str, VALUE opts)
|
||
|
io_read_nonblock(VALUE io, VALUE length, VALUE str, VALUE ex)
|
||
|
{
|
||
|
rb_io_t *fptr;
|
||
|
long n;
|
||
|
long n, len;
|
||
|
struct read_internal_arg arg;
|
||
|
if (!RB_TYPE_P(str, T_STRING))
|
||
|
str = rb_obj_as_string(str);
|
||
|
if ((len = NUM2LONG(length)) < 0) {
|
||
|
rb_raise(rb_eArgError, "negative length %ld given", len);
|
||
|
}
|
||
|
io = GetWriteIO(io);
|
||
|
io_setstrbuf(&str,len);
|
||
|
OBJ_TAINT(str);
|
||
|
GetOpenFile(io, fptr);
|
||
|
rb_io_check_writable(fptr);
|
||
|
rb_io_check_byte_readable(fptr);
|
||
|
if (io_fflush(fptr) < 0)
|
||
|
rb_sys_fail(0);
|
||
|
if (len == 0)
|
||
|
return str;
|
||
|
rb_io_set_nonblock(fptr);
|
||
|
n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
|
||
|
n = read_buffered_data(RSTRING_PTR(str), len, fptr);
|
||
|
if (n <= 0) {
|
||
|
rb_io_set_nonblock(fptr);
|
||
|
io_setstrbuf(&str, len);
|
||
|
arg.fd = fptr->fd;
|
||
|
arg.str_ptr = RSTRING_PTR(str);
|
||
|
arg.len = len;
|
||
|
rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
|
||
|
n = arg.len;
|
||
|
if (n < 0) {
|
||
|
if ((errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||
|
if (ex == Qfalse) return sym_wait_readable;
|
||
|
rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "read would block");
|
||
|
}
|
||
|
rb_sys_fail_path(fptr->pathv);
|
||
|
}
|
||
|
}
|
||
|
io_set_read_length(str, n);
|
||
|
if (n == -1) {
|
||
|
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||
|
if (no_exception_p(opts)) {
|
||
|
return sym_wait_writable;
|
||
|
}
|
||
|
else {
|
||
|
rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "write would block");
|
||
|
}
|
||
|
}
|
||
|
rb_sys_fail_path(fptr->pathv);
|
||
|
if (n == 0) {
|
||
|
if (ex == Qfalse) return Qnil;
|
||
|
rb_eof_error();
|
||
|
}
|
||
|
return LONG2FIX(n);
|
||
|
return str;
|
||
|
}
|
||
|
/*
|
||
| ... | ... | |
|
* return the symbol :wait_writable instead.
|
||
|
*
|
||
|
*/
|
||
|
static VALUE
|
||
|
rb_io_write_nonblock(int argc, VALUE *argv, VALUE io)
|
||
|
io_write_nonblock(VALUE io, VALUE str, VALUE ex)
|
||
|
{
|
||
|
VALUE str, opts;
|
||
|
rb_io_t *fptr;
|
||
|
long n;
|
||
|
rb_scan_args(argc, argv, "10:", &str, &opts);
|
||
|
if (!RB_TYPE_P(str, T_STRING))
|
||
|
str = rb_obj_as_string(str);
|
||
|
return io_write_nonblock(io, str, opts);
|
||
|
io = GetWriteIO(io);
|
||
|
GetOpenFile(io, fptr);
|
||
|
rb_io_check_writable(fptr);
|
||
|
if (io_fflush(fptr) < 0)
|
||
|
rb_sys_fail(0);
|
||
|
rb_io_set_nonblock(fptr);
|
||
|
n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
|
||
|
if (n == -1) {
|
||
|
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||
|
if (ex == Qfalse) {
|
||
|
return sym_wait_writable;
|
||
|
}
|
||
|
else {
|
||
|
rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "write would block");
|
||
|
}
|
||
|
}
|
||
|
rb_sys_fail_path(fptr->pathv);
|
||
|
}
|
||
|
return LONG2FIX(n);
|
||
|
}
|
||
|
/*
|
||
| ... | ... | |
|
rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
|
||
|
rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
|
||
|
rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, -1);
|
||
|
rb_define_private_method(rb_cIO, "__read_nonblock", io_read_nonblock, 3);
|
||
|
rb_define_private_method(rb_cIO, "__write_nonblock", io_write_nonblock, 2);
|
||
|
rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
|
||
|
rb_define_method(rb_cIO, "read", io_read, -1);
|
||
|
rb_define_method(rb_cIO, "write", io_write_m, 1);
|
||
| prelude.rb | ||
|---|---|---|
|
}
|
||
|
end
|
||
|
end
|
||
|
class IO
|
||
|
def read_nonblock(len, buf = nil, exception: true)
|
||
|
__read_nonblock(len, buf, exception)
|
||
|
end
|
||
|
def write_nonblock(buf, exception: true)
|
||
|
__write_nonblock(buf, exception)
|
||
|
end
|
||
|
end
|
||
|
-
|
||