diff options
author | Eric Wong <e@yhbt.net> | 2010-09-29 17:13:21 -0700 |
---|---|---|
committer | Eric Wong <e@yhbt.net> | 2010-09-29 17:13:21 -0700 |
commit | 8fe89997453d6c530c3f5e08bc9c1da40a621248 (patch) | |
tree | d9581ee49b4cf99fa78ff0ab10af470f54082296 | |
parent | 39c851e595970a2349a8a39878afd94a3324e102 (diff) | |
download | kgio-8fe89997453d6c530c3f5e08bc9c1da40a621248.tar.gz |
Partial writes can be retried until completely denied with EAGAIN. Often times, it is beneficial to retry immediately after a partial write because the kernel may allocate more buffers or the reader can drain the buffers. This helps the caller avoid crossing the Ruby <-> C boundary more than necessary.
-rw-r--r-- | ext/kgio/kgio_ext.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/ext/kgio/kgio_ext.c b/ext/kgio/kgio_ext.c index c630ab5..c8a9611 100644 --- a/ext/kgio/kgio_ext.c +++ b/ext/kgio/kgio_ext.c @@ -228,9 +228,9 @@ done: if (errno == EINTR) return -1; if (errno == EAGAIN) { - if (io_wait) { - long written = RSTRING_LEN(a->buf) - a->len; + long written = RSTRING_LEN(a->buf) - a->len; + if (io_wait) { wait_writable(a->io, a->fd); /* buf may be modified in other thread/fiber */ @@ -239,20 +239,19 @@ done: goto done; a->ptr = RSTRING_PTR(a->buf) + written; return -1; + } else if (written > 0) { + a->buf = rb_str_new(a->ptr + n, a->len - n); } else { a->buf = mKgio_WaitWritable; - return 0; } + return 0; } rb_sys_fail(msg); } else { assert(n >= 0 && n < a->len && "write/send syscall broken?"); - if (io_wait) { - a->ptr += n; - a->len -= n; - return -1; - } - a->buf = rb_str_new(a->ptr + n, a->len - n); + a->ptr += n; + a->len -= n; + return -1; } return 0; } @@ -294,10 +293,11 @@ static VALUE kgio_write(VALUE io, VALUE str) * * Returns nil if the write was completed in full. * - * Returns a String containing the unwritten portion if there was a - * partial write. + * Returns a String containing the unwritten portion if EAGAIN + * was encountered, but some portion was successfully written. * - * Returns Kgio::WaitWritable if EAGAIN is encountered. + * Returns Kgio::WaitWritable if EAGAIN is encountered and nothing + * was written. */ static VALUE kgio_trywrite(VALUE io, VALUE str) { |