initial edge-triggered epoll model
[rainbows.git] / lib / rainbows / epoll / server.rb
blob4586c955492c9a8678ff31f8301d43f49936f873
1 # -*- encoding: binary -*-
2 # :nodoc:
3 module Rainbows::Epoll::Server
4   IN = SleepyPenguin::Epoll::IN | SleepyPenguin::Epoll::ET
5   @@nr = 0
6   MAX = Rainbows.server.worker_connections
7   THRESH = MAX - 1
8   include Rainbows::Epoll::State
9   LISTENERS = Rainbows::HttpServer::LISTENERS
10   ReRun = []
12   def self.extended(obj)
13     obj.instance_variable_set(:@epoll_active, false)
14   end
16   def self.run
17     LISTENERS.each { |sock| sock.extend(self).epoll_enable(IN) }
18     begin
19       EP.wait(100, 1000) { |_, obj| obj.epoll_run }
20       while obj = ReRun.shift
21         obj.epoll_run
22       end
23       Rainbows::Epoll::Client.expire
24     rescue => e
25       Rainbows::Error.listen_loop(e)
26     end while Rainbows.tick || @@nr > 0
27   end
29   # rearms all listeners when there's a free slot
30   def self.decr
31     THRESH == (@@nr -= 1) and LISTENERS.each { |sock| sock.epoll_enable(IN) }
32   end
34   def epoll_run
35     return epoll_disable if @@nr >= MAX
36     while io = kgio_tryaccept
37       @@nr += 1
38       # there's a chance the client never even sees epoll for simple apps
39       io.epoll_once
40       return epoll_disable if @@nr >= MAX
41     end
42   end
43 end