doc: misc cleanups and additions for RDoc
[rainbows.git] / lib / rainbows / fiber / io.rb
blobac243a49f3a9e0d0988f8100a27392667e95b744
1 # -*- encoding: binary -*-
3 # A Fiber-aware IO class, gives users the illusion of a synchronous
4 # interface that yields away from the current Fiber whenever
5 # the underlying descriptor is blocked on reads or write
7 # This is a stable, legacy interface and should be preserved for all
8 # future versions of Rainbows!  However, new apps should use
9 # Rainbows::Fiber::IO::Socket or Rainbows::Fiber::IO::Pipe instead.
11 class Rainbows::Fiber::IO
12   attr_accessor :to_io
14   # :stopdoc:
15   # see Rainbows::Fiber::IO::Compat for initialize implementation
16   class << self
17     alias :[] :new
18   end
19   # :startdoc:
21   # no longer used internally within Rainbows!, only for compatibility
22   def write_nonblock(buf)
23     @to_io.write_nonblock(buf)
24   end
26   def kgio_addr
27     @to_io.kgio_addr
28   end
30   # for wrapping output response bodies
31   def each(&block)
32     buf = readpartial(16384)
33     yield buf
34     yield buf while readpartial(16384, buf)
35     rescue EOFError
36       self
37   end
39   def closed?
40     @to_io.closed?
41   end
43   def fileno
44     @to_io.fileno
45   end
47   def write(buf)
48     if @to_io.respond_to?(:kgio_trywrite)
49       begin
50         case rv = @to_io.kgio_trywrite(buf)
51         when nil
52           return
53         when String
54           buf = rv
55         when :wait_writable
56           kgio_wait_writable
57         end
58       end while true
59     else
60       begin
61         (rv = @to_io.write_nonblock(buf)) == buf.bytesize and return
62         buf = byte_slice(buf, rv)
63       rescue Errno::EAGAIN
64         kgio_wait_writable
65       end while true
66     end
67   end
69   def byte_slice(buf, start) # :nodoc:
70     buf.encoding == Encoding::BINARY or
71       buf = buf.dup.force_encoding(Encoding::BINARY)
72     buf.slice(start, buf.size)
73   end
75   # used for reading headers (respecting keepalive_timeout)
76   def timed_read(buf)
77     expire = nil
78     if @to_io.respond_to?(:kgio_tryread)
79       begin
80         case rv = @to_io.kgio_tryread(16384, buf)
81         when :wait_readable
82           return if expire && expire < Time.now
83           expire ||= read_expire
84           kgio_wait_readable
85         else
86           return rv
87         end
88       end while true
89     else
90       begin
91         return @to_io.read_nonblock(16384, buf)
92       rescue Errno::EAGAIN
93         return if expire && expire < Time.now
94         expire ||= read_expire
95         kgio_wait_readable
96       end while true
97     end
98   end
100   def readpartial(length, buf = "")
101     if @to_io.respond_to?(:kgio_tryread)
102       begin
103         rv = @to_io.kgio_tryread(length, buf)
104         case rv
105         when nil
106           raise EOFError, "end of file reached", []
107         when :wait_readable
108           kgio_wait_readable
109         else
110           return rv
111         end
112       end while true
113     else
114       begin
115         return @to_io.read_nonblock(length, buf)
116       rescue Errno::EAGAIN
117         kgio_wait_readable
118       end while true
119     end
120   end
122   def kgio_read(*args)
123     @to_io.kgio_read(*args)
124   end
126   def kgio_read!(*args)
127     @to_io.kgio_read!(*args)
128   end
130   def kgio_trywrite(*args)
131     @to_io.kgio_trywrite(*args)
132   end
134   autoload :Socket, 'rainbows/fiber/io/socket'
135   autoload :Pipe, 'rainbows/fiber/io/pipe'
138 # :stopdoc:
139 require 'rainbows/fiber/io/methods'
140 require 'rainbows/fiber/io/compat'
141 Rainbows::Client.__send__(:include, Rainbows::Fiber::IO::Methods)
142 class Rainbows::Fiber::IO
143   include Rainbows::Fiber::IO::Compat
144   include Rainbows::Fiber::IO::Methods
145   alias_method :wait_readable, :kgio_wait_readable
146   alias_method :wait_writable, :kgio_wait_writable