about summary refs log tree commit homepage
path: root/lib/rainbows/epoll/server.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rainbows/epoll/server.rb')
-rw-r--r--lib/rainbows/epoll/server.rb43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib/rainbows/epoll/server.rb b/lib/rainbows/epoll/server.rb
new file mode 100644
index 0000000..4586c95
--- /dev/null
+++ b/lib/rainbows/epoll/server.rb
@@ -0,0 +1,43 @@
+# -*- encoding: binary -*-
+# :nodoc:
+module Rainbows::Epoll::Server
+  IN = SleepyPenguin::Epoll::IN | SleepyPenguin::Epoll::ET
+  @@nr = 0
+  MAX = Rainbows.server.worker_connections
+  THRESH = MAX - 1
+  include Rainbows::Epoll::State
+  LISTENERS = Rainbows::HttpServer::LISTENERS
+  ReRun = []
+
+  def self.extended(obj)
+    obj.instance_variable_set(:@epoll_active, false)
+  end
+
+  def self.run
+    LISTENERS.each { |sock| sock.extend(self).epoll_enable(IN) }
+    begin
+      EP.wait(100, 1000) { |_, obj| obj.epoll_run }
+      while obj = ReRun.shift
+        obj.epoll_run
+      end
+      Rainbows::Epoll::Client.expire
+    rescue => e
+      Rainbows::Error.listen_loop(e)
+    end while Rainbows.tick || @@nr > 0
+  end
+
+  # rearms all listeners when there's a free slot
+  def self.decr
+    THRESH == (@@nr -= 1) and LISTENERS.each { |sock| sock.epoll_enable(IN) }
+  end
+
+  def epoll_run
+    return epoll_disable if @@nr >= MAX
+    while io = kgio_tryaccept
+      @@nr += 1
+      # there's a chance the client never even sees epoll for simple apps
+      io.epoll_once
+      return epoll_disable if @@nr >= MAX
+    end
+  end
+end