diff options
author | Eric Wong <normalperson@yhbt.net> | 2009-11-25 01:44:34 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2009-11-25 03:13:12 -0800 |
commit | 4d8304bf0aa5665e8f8474dfb96019297fa0c2b9 (patch) | |
tree | 676418a49b5575209c00fb3bcb83db10df8834bc /lib/rainbows/fiber/io.rb | |
parent | 2bc6e7a3c4e972ee3227d931e79bc4057ba278ca (diff) | |
download | rainbows-4d8304bf0aa5665e8f8474dfb96019297fa0c2b9.tar.gz |
This one seems a easy to get working and supports everything we need to support from the server perspective. Apps will need modified drivers, but it doesn't seem too hard to add more/better support for wrapping IO objects with Fiber::IO.
Diffstat (limited to 'lib/rainbows/fiber/io.rb')
-rw-r--r-- | lib/rainbows/fiber/io.rb | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/rainbows/fiber/io.rb b/lib/rainbows/fiber/io.rb new file mode 100644 index 0000000..bc6c0fe --- /dev/null +++ b/lib/rainbows/fiber/io.rb @@ -0,0 +1,65 @@ +# -*- encoding: binary -*- +module Rainbows + module Fiber + + # A partially complete IO wrapper, this exports an IO.select()-able + # #to_io method and gives users the illusion of a synchronous + # interface that yields away from the current Fiber whenever + # the underlying IO object cannot read or write + class IO < Struct.new(:to_io, :f) + + # for wrapping output response bodies + def each(&block) + begin + yield readpartial(16384) + rescue EOFError + break + end while true + self + end + + def close + to_io.close + end + + def write(buf) + begin + (w = to_io.write_nonblock(buf)) == buf.size and return + buf = buf[w..-1] + rescue Errno::EAGAIN + WR[self] = false + ::Fiber.yield + WR.delete(self) + retry + end while true + end + + # used for reading headers (respecting keepalive_timeout) + def read_timeout + expire = false + begin + to_io.read_nonblock(16384) + rescue Errno::EAGAIN + return if expire && expire < Time.now + RD[self] = false + expire = Time.now + G.kato + ::Fiber.yield + RD.delete(self) + retry + end + end + + def readpartial(length, buf = "") + begin + to_io.read_nonblock(length, buf) + rescue Errno::EAGAIN + RD[self] = false + ::Fiber.yield + RD.delete(self) + retry + end + end + + end + end +end |