class Strand::ConditionVariable
Provides for Strands (Fibers) what Ruby's ConditionVariable
provides for Threads.
Public Class Methods
new()
click to toggle source
Create a new condition variable.
# File lib/strand/condition_variable.rb, line 6 def initialize @waiters = [] end
Public Instance Methods
signal()
click to toggle source
Asynchronously resume a fiber waiting on this condition variable. The waiter is not resumed immediately, but on the next tick of EM's reactor loop.
cond = Strand::ConditionVariable.new Strand.new{ puts 1; cond.wait; puts 2 } puts 3 cond.signal puts 4 # output is... 1 3 4 2
# File lib/strand/condition_variable.rb, line 66 def signal # If there are no waiters, do nothing. return if @waiters.empty? # Find a waiter to wake up. waiter = @waiters.shift # Resume it on next tick. EM.next_tick{ waiter.resume } end
wait(timeout = nil)
click to toggle source
Wait until signaled. Returns true upon returning.
x = nil cond = Strand::ConditionVariable.new Strand.new{ cond.wait; x = 1; cond.signal } puts x # => nil cond.signal cond.wait # => true puts x # => 1
If timeout is a number, then returns false if timed out or true if signaled.
x = nil cond = Strand::ConditionVariable.new Strand.new{ cond.wait; x = 1; cond.signal } puts x # => nil cond.wait(0.01) # => false puts x # => nil
# File lib/strand/condition_variable.rb, line 25 def wait(timeout = nil) # Get the fiber that called us. fiber = Fiber.current # Add the fiber to the list of waiters. @waiters << fiber # Setup the timer if they specified a timeout timer = EM::Timer.new(timeout){ fiber.resume(:timeout) } if timeout # Wait for signal or timeout. if Fiber.yield == :timeout # Timeout occurred. # Remove from list of waiters. @waiters.delete(fiber) false else # Ok we were signaled. # Cancel the timer if there is one. timer.cancel if timer true end end