diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-02-27 23:40:44 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-02-28 00:15:00 +0000 |
commit | 813c5300294046f9ae0f4bac8449a4734ddd7fd9 (patch) | |
tree | 74184d5ad46051031ff8013f276bd96019e76fba /ext/io_splice | |
parent | c32ddca888259c391e126154ff62fdcdb2e3759c (diff) | |
download | ruby_io_splice-813c5300294046f9ae0f4bac8449a4734ddd7fd9.tar.gz |
This allows more-efficient use of non-blocking I/O with tee(2) and will return :EAGAIN instead of generating an expensive Errno::EAGAIN exception.
Diffstat (limited to 'ext/io_splice')
-rw-r--r-- | ext/io_splice/io_splice_ext.c | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/ext/io_splice/io_splice_ext.c b/ext/io_splice/io_splice_ext.c index 79d96ee..c97435e 100644 --- a/ext/io_splice/io_splice_ext.c +++ b/ext/io_splice/io_splice_ext.c @@ -222,6 +222,20 @@ static VALUE nogvl_tee(void *ptr) return (VALUE)tee(a->fd_in, a->fd_out, a->len, a->flags); } +static long do_tee(int argc, VALUE *argv, unsigned dflags) +{ + VALUE fd_in, fd_out, len, flags; + struct tee_args a; + + rb_scan_args(argc, argv, "31", &fd_in, &fd_out, &len, &flags); + a.fd_in = my_fileno(fd_in); + a.fd_out = my_fileno(fd_out); + a.len = (size_t)NUM2ULONG(len); + a.flags = NIL_P(flags) ? dflags : NUM2UINT(flags) | dflags; + + return (long)nb_io_run(nogvl_tee, &a, a.flags); +} + /* * call-seq: * IO.tee(fd_in, fd_out, len, flags) => integer @@ -241,19 +255,10 @@ static VALUE nogvl_tee(void *ptr) * See manpage for full documentation: * http://kernel.org/doc/man-pages/online/pages/man2/tee.2.html */ -static VALUE my_tee(VALUE self, - VALUE fd_in, VALUE fd_out, - VALUE len, VALUE flags) +static VALUE my_tee(int argc, VALUE *argv, VALUE self) { - long n; - struct tee_args a = { - .fd_in = my_fileno(fd_in), - .fd_out = my_fileno(fd_out), - .len = (size_t)NUM2ULONG(len), - .flags = NUM2UINT(flags), - }; - - n = (long)nb_io_run(nogvl_tee, &a, a.flags); + long n = do_tee(argc, argv, 0); + if (n == 0) rb_eof_error(); if (n < 0) @@ -262,6 +267,21 @@ static VALUE my_tee(VALUE self, return LONG2NUM(n); } +static VALUE trytee(int argc, VALUE *argv, VALUE self) +{ + long n = do_tee(argc, argv, SPLICE_F_NONBLOCK); + + if (n == 0) + return Qnil; + if (n < 0) { + if (errno == EAGAIN) + return sym_EAGAIN; + rb_sys_fail("tee"); + } + + return LONG2NUM(n); +} + struct vmsplice_args { int fd; struct iovec *iov; @@ -472,7 +492,8 @@ void Init_io_splice_ext(void) rb_define_singleton_method(rb_cIO, "splice", my_splice, -1); rb_define_singleton_method(rb_cIO, "trysplice", trysplice, -1); - rb_define_singleton_method(rb_cIO, "tee", my_tee, 4); + rb_define_singleton_method(rb_cIO, "tee", my_tee, -1); + rb_define_singleton_method(rb_cIO, "trytee", trytee, -1); rb_define_singleton_method(rb_cIO, "vmsplice", my_vmsplice, 3); /* |