about summary refs log tree commit homepage
path: root/lib/rainbows/xepoll
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-05-08 07:22:36 +0000
committerEric Wong <normalperson@yhbt.net>2011-05-08 07:22:36 +0000
commite64e2e0045d63c4edd291839febba978534be652 (patch)
tree32d0435c385f3ac932415bae609e4c13f8fcaed1 /lib/rainbows/xepoll
parent07a0bee9dd6f2c366d11284b7e9ab09d66b411e4 (diff)
downloadrainbows-e64e2e0045d63c4edd291839febba978534be652.tar.gz
worker_yield is safer than setting a threshold with multiple
acceptors when thread limits are hit.  Also, avoid sleep +
Thread#run since it's potentially racy if threads are extremely
unfairly scheduled.

Same things applied to xepoll_thread_spawn.
Diffstat (limited to 'lib/rainbows/xepoll')
-rw-r--r--lib/rainbows/xepoll/client.rb36
1 files changed, 19 insertions, 17 deletions
diff --git a/lib/rainbows/xepoll/client.rb b/lib/rainbows/xepoll/client.rb
index 6cae2f1..c7eebcc 100644
--- a/lib/rainbows/xepoll/client.rb
+++ b/lib/rainbows/xepoll/client.rb
@@ -5,28 +5,30 @@ module Rainbows::XEpoll::Client
   N = Raindrops.new(1)
   Rainbows::Epoll.nr_clients = lambda { N[0] }
   include Rainbows::Epoll::Client
-  MAX = Rainbows.server.worker_connections
-  THRESH = MAX - 1
   EP = Rainbows::Epoll::EP
-  THREADS = Rainbows::HttpServer::LISTENERS.map do |sock|
-    Thread.new do
-      sleep
-      begin
-        if io = sock.kgio_accept
-          N.incr(0, 1)
-          io.epoll_once
-        end
-        sleep while N[0] >= MAX
-      rescue => e
-        Rainbows::Error.listen_loop(e)
-      end while Rainbows.alive
+  ACCEPTORS = Rainbows::HttpServer::LISTENERS.dup
+  extend Rainbows::WorkerYield
+
+  def self.included(klass)
+    max = Rainbows.server.worker_connections
+    ACCEPTORS.map! do |sock|
+      Thread.new do
+        begin
+          if io = sock.kgio_accept(klass)
+            N.incr(0, 1)
+            io.epoll_once
+          end
+          worker_yield while N[0] >= max
+        rescue => e
+          Rainbows::Error.listen_loop(e)
+        end while Rainbows.alive
+      end
     end
   end
 
   def self.run
-    THREADS.each { |t| t.run }
     Rainbows::Epoll.loop
-    Rainbows::JoinThreads.acceptors(THREADS)
+    Rainbows::JoinThreads.acceptors(ACCEPTORS)
   end
 
   # only call this once
@@ -40,6 +42,6 @@ module Rainbows::XEpoll::Client
 
   def on_close
     KATO.delete(self)
-    N.decr(0, 1) == THRESH and THREADS.each { |t| t.run }
+    N.decr(0, 1)
   end
 end