upgrade to Kgio 2.x and Unicorn 3.x
[rainbows.git] / lib / rainbows / fiber / base.rb
blob69bf5d9510756cf5b031eb961d05aa6a752c09a7
1 # -*- encoding: binary -*-
2 # :enddoc:
3 require 'rainbows/fiber/io'
5 module Rainbows::Fiber::Base
7   include Rainbows::Base
9   # :stopdoc:
10   RD = Rainbows::Fiber::RD
11   WR = Rainbows::Fiber::WR
12   ZZ = Rainbows::Fiber::ZZ
13   # :startdoc:
15   # the scheduler method that powers both FiberSpawn and FiberPool
16   # concurrency models.  It times out idle clients and attempts to
17   # schedules ones that were blocked on I/O.  At most it'll sleep
18   # for one second (returned by the schedule_sleepers method) which
19   # will cause it.
20   def schedule(&block)
21     ret = begin
22       G.tick
23       RD.compact.each { |c| c.f.resume } # attempt to time out idle clients
24       t = schedule_sleepers
25       Kernel.select(RD.compact.concat(LISTENERS), WR.compact, nil, t) or return
26     rescue Errno::EINTR
27       retry
28     rescue Errno::EBADF, TypeError
29       LISTENERS.compact!
30       raise
31     end or return
33     # active writers first, then _all_ readers for keepalive timeout
34     ret[1].concat(RD.compact).each { |c| c.f.resume }
36     # accept is an expensive syscall, filter out listeners we don't want
37     (ret[0] & LISTENERS).each(&block)
38   end
40   # wakes up any sleepers that need to be woken and
41   # returns an interval to IO.select on
42   def schedule_sleepers
43     max = nil
44     now = Time.now
45     fibs = []
46     ZZ.delete_if { |fib, time|
47       if now >= time
48         fibs << fib
49       else
50         max = time
51         false
52       end
53     }
54     fibs.each { |fib| fib.resume }
55     now = Time.now
56     max.nil? || max > (now + 1) ? 1 : max - now
57   end
59   def process(client)
60     G.cur += 1
61     process_client(client)
62   ensure
63     G.cur -= 1
64     ZZ.delete(client.f)
65   end
67   def self.setup(klass, app)
68     require 'rainbows/fiber/body'
69     klass.__send__(:include, Rainbows::Fiber::Body)
70     self.const_set(:APP, app)
71   end
72 end