copy_stream attempts to use IO::Splice::WAITALL
authorEric Wong <normalperson@yhbt.net>
Tue, 10 May 2011 19:42:38 +0000 (10 12:42 -0700)
committerEric Wong <normalperson@yhbt.net>
Tue, 10 May 2011 19:42:38 +0000 (10 12:42 -0700)
This reduces Ruby method dispatches

lib/io/splice.rb

index 4ec44e4..0802c3b 100644 (file)
@@ -1,5 +1,6 @@
 # -*- encoding: binary -*-
 require 'io_splice_ext'
+require 'io/wait'
 
 module IO::Splice
 
@@ -39,14 +40,13 @@ module IO::Splice
     dst.kind_of?(String) and close << (dst = File.open(dst, "w"))
     src, dst = src.to_io, dst.to_io
     rv = len
-    select_args = selectable(src, dst)
 
     if src.stat.pipe? || dst.stat.pipe?
       if len
-        len -= full(src, dst, len, src_offset, select_args) until len == 0
+        len -= full(src, dst, len, src_offset) until len == 0
       else
         rv = 0
-        while n = partial(src, dst, PIPE_CAPA, src_offset, select_args)
+        while n = partial(src, dst, PIPE_CAPA, src_offset)
           rv += n
         end
       end
@@ -54,13 +54,13 @@ module IO::Splice
       r, w = tmp = IO.pipe
       close.concat(tmp)
       if len
-        while len != 0 && n = partial(src, w, len, src_offset, select_args)
-          len -= full(r, dst, n, nil, select_args)
+        while len != 0 && n = partial(src, w, len, src_offset)
+          len -= full(r, dst, n, nil)
         end
       else
         rv = 0
-        while n = partial(src, w, PIPE_CAPA, src_offset, select_args)
-          rv += full(r, dst, n, nil, select_args)
+        while n = partial(src, w, PIPE_CAPA, src_offset)
+          rv += full(r, dst, n, nil)
         end
       end
     end
@@ -76,17 +76,8 @@ module IO::Splice
   # This will block and wait for IO completion of +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, src_offset, _select_args = selectable(src, dst))
-    nr = len
-    while nr > 0
-      n = partial(src, dst, nr, src_offset, _select_args) or
-                                     raise EOFError, "end of file reached"
-      nr -= n
-    end
-    len
+  def self.full(src, dst, len, src_offset)
+    IO.splice(src, src_offset, dst, nil, len, F_MOVE | WAITALL)
   end
 
   # splice up to +len+ bytes from +src+ to +dst+.
@@ -94,22 +85,16 @@ module IO::Splice
   # may BOTH be pipes in Linux 2.6.31 or later.
   # Returns the number of bytes actually spliced.
   # Like IO#readpartial, this never returns Errno::EAGAIN
-  # 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.partial(src, dst, len, src_offset,
-                   _select_args = selectable(src, dst))
-    begin
-      rv = IO.trysplice(src, src_offset, 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
-  def self.selectable(src, dst) # :nodoc:
-    rv = []
-    src.stat.pipe? or rv[0] = [ src ]
-    dst.stat.pipe? or rv[1] = [ dst ]
-    rv
+  def self.partial(src, dst, len, src_offset)
+    IO.splice(src, src_offset, dst, nil, len, F_MOVE)
+    rescue EOFError
+      nil
+    rescue Errno::EAGAIN
+      begin
+        src.to_io.wait
+        IO.select(nil, [dst])
+        rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
+      end while rv == :EAGAIN
+      rv
   end
 end