add RevThreadPool concurrency model
[rainbows.git] / lib / rainbows / rev / thread.rb
blob8fa43ac2b10046ff6c3b51f5ce7ce9bef84fe46e
1 # -*- encoding: binary -*-
2 require 'thread'
3 require 'rainbows/rev/master'
5 module Rainbows
6   module Rev
8     class ThreadClient < Client
10       def app_call
11         KATO.delete(self)
12         disable
13         @env[RACK_INPUT] = @input
14         @input = nil # not sure why, @input seems to get closed otherwise...
15         app_dispatch # must be implemented by subclass
16       end
18       # this is only called in the master thread
19       def response_write(response)
20         enable
21         alive = @hp.keepalive? && G.alive
22         out = [ alive ? CONN_ALIVE : CONN_CLOSE ] if @hp.headers?
23         DeferredResponse.write(self, response, out)
24         return quit unless alive && G.alive
26         @env.clear
27         @hp.reset
28         @state = :headers
29         # keepalive requests are always body-less, so @input is unchanged
30         if @hp.headers(@env, @buf)
31           @input = HttpRequest::NULL_IO
32           app_call
33         else
34           KATO[self] = Time.now
35         end
36       end
38       # fails-safe application dispatch, we absolutely cannot
39       # afford to fail or raise an exception (killing the thread)
40       # here because that could cause a deadlock and we'd leak FDs
41       def app_response
42         begin
43           @env[REMOTE_ADDR] = @remote_addr
44           APP.call(@env.update(RACK_DEFAULTS))
45         rescue => e
46           Error.app(e) # we guarantee this does not raise
47           [ 500, {}, [] ]
48         end
49       end
51     end
52   end
53 end