Class: Strand::ConditionVariable
- Inherits:
-
Object
- Object
- Strand::ConditionVariable
- Defined in:
- lib/strand/condition_variable.rb
Overview
Provides for Strands (Fibers) what Ruby’s ConditionVariable provides for Threads.
Instance Method Summary collapse
-
#initialize ⇒ ConditionVariable
constructor
Create a new condition variable.
-
#signal ⇒ Object
Asynchronously resume a fiber waiting on this condition variable.
-
#wait(timeout = nil) ⇒ Object
Wait until signaled.
Constructor Details
#initialize ⇒ ConditionVariable
Create a new condition variable.
6 7 8 |
# File 'lib/strand/condition_variable.rb', line 6 def initialize @waiters = [] end |
Instance Method Details
#signal ⇒ Object
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
66 67 68 69 70 71 72 73 74 75 |
# 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) ⇒ Object
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
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# 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 |