about summary refs log tree commit homepage
path: root/lib/rainbows/thread_pool.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-11-28 19:42:53 -0800
committerEric Wong <normalperson@yhbt.net>2009-11-29 12:35:44 -0800
commit37a560c5d14c15a3da7f2c10c9ea3d6002b34fe1 (patch)
tree8d163646e4ba3586cafde788804c580e3315431c /lib/rainbows/thread_pool.rb
parent50fb5151bd44137adace51a0652f4d01d851790c (diff)
downloadrainbows-37a560c5d14c15a3da7f2c10c9ea3d6002b34fe1.tar.gz
It's a tad faster for non-keepalive connections and should do
better on large SMP machines with many workers AND threads.
That means the ActorSpawn model in Rubinius is nothing more than
ThreadSpawn underneath (for now).
Diffstat (limited to 'lib/rainbows/thread_pool.rb')
-rw-r--r--lib/rainbows/thread_pool.rb51
1 files changed, 28 insertions, 23 deletions
diff --git a/lib/rainbows/thread_pool.rb b/lib/rainbows/thread_pool.rb
index f398828..917b835 100644
--- a/lib/rainbows/thread_pool.rb
+++ b/lib/rainbows/thread_pool.rb
@@ -27,39 +27,44 @@ module Rainbows
 
     def worker_loop(worker)
       init_worker_process(worker)
-      pool = (1..worker_connections).map { new_worker_thread }
+      pool = (1..worker_connections).map do
+        Thread.new { LISTENERS.size == 1 ? sync_worker : async_worker }
+      end
 
       while G.alive
         # if any worker dies, something is serious wrong, bail
         pool.each do |thr|
-          G.tick
+          G.tick or break
           thr.join(1) and G.quit!
         end
       end
       join_threads(pool)
     end
 
-    def new_worker_thread
-      Thread.new {
-        begin
-          begin
-            # TODO: check if select() or accept() is a problem on large
-            # SMP systems under Ruby 1.9.  Hundreds of native threads
-            # all working off the same socket could be a thundering herd
-            # problem.  On the other hand, a thundering herd may not
-            # even incur as much overhead as an extra Mutex#synchronize
-            ret = IO.select(LISTENERS, nil, nil, 1) and
-                  ret.first.each do |s|
-                    s = Rainbows.accept(s) and process_client(s)
-                  end
-          rescue Errno::EINTR
-          rescue Errno::EBADF, TypeError
-            break
-          end
-        rescue => e
-          Error.listen_loop(e)
-        end while G.alive
-      }
+    def sync_worker
+      s = LISTENERS.first
+      begin
+        process_client(s.accept)
+      rescue Errno::EINTR, Errno::ECONNABORTED
+      rescue => e
+        Error.listen_loop(e)
+      end while G.alive
+    end
+
+    def async_worker
+      begin
+        # TODO: check if select() or accept() is a problem on large
+        # SMP systems under Ruby 1.9.  Hundreds of native threads
+        # all working off the same socket could be a thundering herd
+        # problem.  On the other hand, a thundering herd may not
+        # even incur as much overhead as an extra Mutex#synchronize
+        ret = IO.select(LISTENERS, nil, nil, 1) and ret.first.each do |s|
+          s = Rainbows.accept(s) and process_client(s)
+        end
+      rescue Errno::EINTR
+      rescue => e
+        Error.listen_loop(e)
+      end while G.alive
     end
 
   end