From 7f11b212f78a5070bea17bc20af43395b6cc621d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 25 Nov 2009 15:08:25 -0800 Subject: Fiber*: add Rainbows::Fiber.sleep method 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. --- lib/rainbows/fiber.rb | 24 ++++++++++++++++++++++++ lib/rainbows/fiber_pool.rb | 2 +- lib/rainbows/fiber_spawn.rb | 2 +- t/sleep.ru | 2 ++ 4 files changed, 28 insertions(+), 2 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 diff --git a/lib/rainbows/fiber_pool.rb b/lib/rainbows/fiber_pool.rb index ff693fa..6cb2ca6 100644 --- a/lib/rainbows/fiber_pool.rb +++ b/lib/rainbows/fiber_pool.rb @@ -32,7 +32,7 @@ module Rainbows begin ret = begin G.tick - IO.select(rd.keys.concat(LISTENERS), wr.keys, nil, 1) or next + IO.select(rd.keys.concat(LISTENERS), wr.keys, nil, timer) or next rescue Errno::EINTR retry rescue Errno::EBADF, TypeError diff --git a/lib/rainbows/fiber_spawn.rb b/lib/rainbows/fiber_spawn.rb index 969c05b..004976a 100644 --- a/lib/rainbows/fiber_spawn.rb +++ b/lib/rainbows/fiber_spawn.rb @@ -23,7 +23,7 @@ module Rainbows begin ret = begin - IO.select(rd.keys.concat(LISTENERS), wr.keys, nil, 1) or next + IO.select(rd.keys.concat(LISTENERS), wr.keys, nil, timer) or next rescue Errno::EINTR G.tick retry diff --git a/t/sleep.ru b/t/sleep.ru index 9e4eff1..2df22ce 100644 --- a/t/sleep.ru +++ b/t/sleep.ru @@ -8,6 +8,8 @@ run lambda { |env| env["PATH_INFO"] =~ %r{/([\d\.]+)\z} and nr = $1.to_f (case env['rainbows.model'] + when :FiberPool, :FiberSpawn + Rainbows::Fiber when :Revactor Actor else -- cgit v1.2.3-24-ge0c7