less leaky abstraction, more consistent wiht IO

This commit is contained in:
Loic Nageleisen 2012-11-06 16:32:45 +01:00
parent 471e9d51ae
commit 325b9df826

39
tee.rb
View file

@ -26,21 +26,15 @@ class IO
end end
def tee(*procs) def tee(*procs)
ios = procs.map do |proc| ios = procs.map { |proc| FiberChunkedIO.new &proc }
FiberChunkedIO.new &proc
end
chunks.each do |chunk| chunks.each do |chunk|
# for each proc ios.each do |io|
# - copy chunk into its dedicated IO stream
# - resume
ios.each.with_index do |io, i|
$stdout.puts "#{i}:#{tell}"
io.write chunk io.write chunk
io.resume
end end
end end
ios.map { |io| io.resume } ios.each { |io| io.close }
ios.map { |io| io.result }
end end
end end
@ -48,13 +42,25 @@ class FiberChunkedIO
def initialize(chunk_size=1024, &block) def initialize(chunk_size=1024, &block)
@chunk_size = chunk_size @chunk_size = chunk_size
@chunks = [] @chunks = []
@eof = false
@fiber = Fiber.new do @fiber = Fiber.new do
@result = block.call self @result = block.call self
end end
@fiber.resume
end end
def resume # Being a stream, it behaves like IO#eof? and blocks until the other end sends some data or closes it.
def eof?
Fiber.yield
@eof
end
def close
@eof = true
@fiber.resume @fiber.resume
end
def result
@result @result
end end
@ -64,6 +70,8 @@ class FiberChunkedIO
end end
@chunks << chunk @chunks << chunk
@eof = false
@fiber.resume
chunk.size chunk.size
end end
@ -77,10 +85,7 @@ class FiberChunkedIO
def chunks(chunk_size=1024) def chunks(chunk_size=1024)
Enumerator.new do |y| Enumerator.new do |y|
while chunk = read(chunk_size) y << read(chunk_size) until eof?
y << chunk
Fiber.yield
end
end end
end end
end end
@ -103,6 +108,8 @@ File.open("test") do |f|
f.chunks.each { |chunk| puts chunk.length } f.chunks.each { |chunk| puts chunk.length }
end end
p f.tee(sha1_proc, sha2_proc, puts_proc) results = f.tee(sha1_proc, sha2_proc, puts_proc)
p results
p File.read('sums').lines.map.with_index { |l, i| results[i] == l.split(' ')[0] }
end end