about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/rainbows.rb1
-rw-r--r--lib/rainbows/thread_spawn.rb12
-rw-r--r--lib/rainbows/worker_yield.rb15
-rw-r--r--lib/rainbows/writer_thread_spawn/client.rb5
4 files changed, 20 insertions, 13 deletions
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index adbc37c..1f8b252 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -113,6 +113,7 @@ module Rainbows
   autoload :StreamFile, 'rainbows/stream_file'
   autoload :HttpResponse, 'rainbows/http_response' # deprecated
   autoload :ThreadTimeout, 'rainbows/thread_timeout'
+  autoload :WorkerYield, 'rainbows/worker_yield'
 end
 
 require 'rainbows/error'
diff --git a/lib/rainbows/thread_spawn.rb b/lib/rainbows/thread_spawn.rb
index a0ccde6..9da75f1 100644
--- a/lib/rainbows/thread_spawn.rb
+++ b/lib/rainbows/thread_spawn.rb
@@ -18,6 +18,7 @@ module Rainbows
 
   module ThreadSpawn
     include Base
+    include Rainbows::WorkerYield
 
     def accept_loop(klass) #:nodoc:
       lock = Mutex.new
@@ -26,16 +27,7 @@ module Rainbows
         klass.new(l) do |l|
           begin
             if lock.synchronize { G.cur >= limit }
-              # Sleep if we're busy, another less busy worker process may
-              # take it for us if we sleep. This is gross but other options
-              # still suck because they require expensive/complicated
-              # synchronization primitives for _every_ case, not just this
-              # unlikely one.  Since this case is (or should be) uncommon,
-              # just busy wait when we have to.
-              # We don't use Thread.pass because it needlessly spins the
-              # CPU during I/O wait, CPU cycles that can be better used
-              # by other worker _processes_.
-              sleep(0.01)
+              worker_yield
             elsif c = l.kgio_accept
               klass.new(c) do |c|
                 begin
diff --git a/lib/rainbows/worker_yield.rb b/lib/rainbows/worker_yield.rb
new file mode 100644
index 0000000..ec2a289
--- /dev/null
+++ b/lib/rainbows/worker_yield.rb
@@ -0,0 +1,15 @@
+# :enddoc:
+module Rainbows::WorkerYield
+
+  # Sleep if we're busy (and let other threads run).  Another less busy
+  # worker process may take it for us if we sleep. This is gross but
+  # other options still suck because they require expensive/complicated
+  # synchronization primitives for _every_ case, not just this unlikely
+  # one.  Since this case is (or should be) uncommon, just busy wait
+  # when we have to.  We don't use Thread.pass because it needlessly
+  # spins the CPU during I/O wait, CPU cycles that can be better used by
+  # other worker _processes_.
+  def worker_yield
+    sleep(0.01)
+  end
+end
diff --git a/lib/rainbows/writer_thread_spawn/client.rb b/lib/rainbows/writer_thread_spawn/client.rb
index f9c373e..ed60f42 100644
--- a/lib/rainbows/writer_thread_spawn/client.rb
+++ b/lib/rainbows/writer_thread_spawn/client.rb
@@ -4,6 +4,7 @@
 class Rainbows::WriterThreadSpawn::Client < Struct.new(:to_io, :q, :thr)
   include Rainbows::Response
   include Rainbows::SocketProxy
+  include Rainbows::WorkerYield
 
   CUR = {} # :nodoc:
 
@@ -17,12 +18,10 @@ class Rainbows::WriterThreadSpawn::Client < Struct.new(:to_io, :q, :thr)
   end
 
   def queue_writer
-    # not using Thread.pass here because that spins the CPU during
-    # I/O wait and will eat cycles from other worker processes.
     until CUR.size < MAX
       CUR.delete_if { |t,_|
         t.alive? ? t.join(0) : true
-      }.size >= MAX and sleep(0.01)
+      }.size >= MAX and worker_yield
     end
 
     q = Queue.new