about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-02-26 14:40:48 -0800
committerEric Wong <normalperson@yhbt.net>2011-02-26 14:40:48 -0800
commitfd131dcbf7a9c098099c00790f504908bc2c94a4 (patch)
treec4fabe0a5f2d6e2c0b51a89162d4abc85fe808db
parentb9119424bdd41e417afae354329e9b6d298baff4 (diff)
downloadruby_io_splice-fd131dcbf7a9c098099c00790f504908bc2c94a4.tar.gz
Things should be slightly faster this way.
-rw-r--r--lib/io/splice.rb44
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