diff options
author | Eric Wong <normalperson@yhbt.net> | 2011-02-26 14:40:48 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2011-02-26 14:40:48 -0800 |
commit | fd131dcbf7a9c098099c00790f504908bc2c94a4 (patch) | |
tree | c4fabe0a5f2d6e2c0b51a89162d4abc85fe808db | |
parent | b9119424bdd41e417afae354329e9b6d298baff4 (diff) | |
download | ruby_io_splice-fd131dcbf7a9c098099c00790f504908bc2c94a4.tar.gz |
Things should be slightly faster this way.
-rw-r--r-- | lib/io/splice.rb | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/lib/io/splice.rb b/lib/io/splice.rb index 13df7ef..af50afc 100644 --- a/lib/io/splice.rb +++ b/lib/io/splice.rb @@ -28,8 +28,9 @@ module IO::Splice end # copies the contents of the IO object given by +src+ to +dst+ - # If len is specified, then only len bytes are copied. Otherwise - # the copy will be until EOF is reached on the +src+. + # If +len+ is specified, then only +len+ bytes are copied and + # +EOFError+ is raised if fewer than +len+ bytes could be copied. + # Otherwise the copy will be until EOF is reached on the +src+. # +src+ and +dst+ must be IO objects or respond to +to_io+ def self.copy_stream(src, dst, len = nil, src_offset = nil) close = [] @@ -45,28 +46,22 @@ module IO::Splice len -= full(src, dst, len, select_args) until len == 0 else rv = 0 - begin - rv += partial(src, dst, PIPE_CAPA, select_args) - rescue EOFError - break - end while true + while n = partial(src, dst, PIPE_CAPA, select_args) + rv += n + end end else r, w = tmp = IO.pipe close.concat(tmp) if len - while len != 0 - nr = partial(src, w, len, select_args) - len -= full(r, dst, nr, select_args) + while len != 0 && n = partial(src, w, len, select_args) + len -= full(r, dst, n, select_args) end else rv = 0 - begin - nr = partial(src, w, PIPE_CAPA, select_args) - rv += full(r, dst, nr, select_args) - rescue EOFError - break - end while true + while n = partial(src, w, PIPE_CAPA, select_args) + rv += full(r, dst, n, select_args) + end end end @@ -79,13 +74,18 @@ module IO::Splice # Either +dst+ or +src+ must be a pipe. +dst+ and +src+ # may BOTH be pipes in Linux 2.6.31 or later. # This will block and wait for IO completion of +len+ - # bytes. Returns the nubmer of bytes actually spliced (always +len+) + # Raises +EOFError+ if end of file is reached. + # bytes. Returns the number of bytes actually spliced (always +len+) # The +_select_args+ parameter is reserved for internal use and # may be removed in future versions. Do not write code that # depends on +_select_args+. def self.full(src, dst, len, _select_args = selectable(src, dst)) nr = len - nr -= partial(src, dst, nr, _select_args) until nr == 0 + while nr > 0 + n = partial(src, dst, nr, _select_args) or + raise EOFError, "end of file reached" + nr -= n + end len end @@ -99,11 +99,9 @@ module IO::Splice # depends on +_select_args+. def self.partial(src, dst, len, _select_args = selectable(src, dst)) begin - IO.splice(src, nil, dst, nil, len, F_MOVE) - rescue Errno::EAGAIN - IO.select(*_select_args) - retry - end + rv = IO.trysplice(src, nil, dst, nil, len, F_MOVE) + end while rv == :EAGAIN and IO.select(*_select_args) + rv end # returns an array suitable for splat-ing to IO.select for blocking I/O |