about summary refs log tree commit homepage
path: root/lib/rainbows/fiber.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-11-25 15:08:25 -0800
committerEric Wong <normalperson@yhbt.net>2009-11-25 15:12:13 -0800
commit7f11b212f78a5070bea17bc20af43395b6cc621d (patch)
treedcef21ffe3a2bac7950293656fb8128a8e13c84c /lib/rainbows/fiber.rb
parent06de4af18d1ba3b28e49e9d8f700df4eca36e635 (diff)
downloadrainbows-7f11b212f78a5070bea17bc20af43395b6cc621d.tar.gz
It works exactly like Actor.sleep and similar to Kernel.sleep
(no way to sleep indefinitely), but is compatible with the
IO.select-based Fiber scheduler we run.  This method only works
within the context of a Rainbows! application dispatch.
Diffstat (limited to 'lib/rainbows/fiber.rb')
-rw-r--r--lib/rainbows/fiber.rb24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/rainbows/fiber.rb b/lib/rainbows/fiber.rb
index e7d64ca..94502a3 100644
--- a/lib/rainbows/fiber.rb
+++ b/lib/rainbows/fiber.rb
@@ -6,10 +6,33 @@ module Rainbows
   module Fiber
     RD = {}
     WR = {}
+    ZZ = {}
+
+    def self.sleep(seconds)
+      ZZ[::Fiber.current] = Time.now + seconds
+      ::Fiber.yield
+    end
 
     module Base
       include Rainbows::Base
 
+      # wakes up any sleepers that need to be woken and
+      # returns an interval to IO.select on
+      def timer
+        max = nil
+        now = Time.now
+        ZZ.delete_if { |fib, time|
+          if now >= time
+            fib.resume
+            now = Time.now
+          else
+            max = time
+            false
+          end
+        }
+        max.nil? || max > (now + 1) ? 1 : max - now
+      end
+
       def process_client(client)
         G.cur += 1
         io = client.to_io
@@ -46,6 +69,7 @@ module Rainbows
         G.cur -= 1
         RD.delete(client)
         WR.delete(client)
+        ZZ.delete(client.f)
       end
 
     end