Class: ConditionVariable
- Inherits:
-
Object
- Object
- ConditionVariable
- Defined in:
- lib/rubysl/thread/thread.rb
Overview
ConditionVariable objects augment class Mutex. Using condition variables, it is possible to suspend while in the middle of a critical section until a resource becomes available.
Example:
require 'thread'
mutex = Mutex.new
resource = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
# Thread 'a' now needs the resource
resource.wait(mutex)
# 'a' can now have the resource
}
}
b = Thread.new {
mutex.synchronize {
# Thread 'b' has finished using the resource
resource.signal
}
}
Instance Method Summary collapse
-
#broadcast ⇒ Object
Wakes up all threads waiting for this lock.
-
#initialize ⇒ ConditionVariable
constructor
Creates a new ConditionVariable.
-
#signal ⇒ Object
Wakes up the first thread in line waiting for this lock.
-
#wait(mutex, timeout = nil) ⇒ Object
Releases the lock held in
mutex
and waits; reacquires the lock on wakeup.
Constructor Details
#initialize ⇒ ConditionVariable
Creates a new ConditionVariable
46 47 48 |
# File 'lib/rubysl/thread/thread.rb', line 46 def initialize @waiters = [] end |
Instance Method Details
#broadcast ⇒ Object
Wakes up all threads waiting for this lock.
101 102 103 104 105 106 107 108 109 |
# File 'lib/rubysl/thread/thread.rb', line 101 def broadcast Rubinius.lock(self) begin @waiters.shift << true until @waiters.empty? ensure Rubinius.unlock(self) end self end |
#signal ⇒ Object
Wakes up the first thread in line waiting for this lock.
88 89 90 91 92 93 94 95 96 |
# File 'lib/rubysl/thread/thread.rb', line 88 def signal Rubinius.lock(self) begin @waiters.shift << true unless @waiters.empty? ensure Rubinius.unlock(self) end self end |
#wait(mutex, timeout = nil) ⇒ Object
Releases the lock held in mutex
and waits; reacquires the lock on wakeup.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rubysl/thread/thread.rb', line 53 def wait(mutex, timeout=nil) Rubinius.lock(self) begin wchan = Rubinius::Channel.new begin mutex.unlock @waiters.push wchan Rubinius.unlock(self) signaled = wchan.receive_timeout timeout ensure mutex.lock Rubinius.lock(self) unless signaled or @waiters.delete(wchan) # we timed out, but got signaled afterwards (e.g. while waiting to # acquire @lock), so pass that signal on to the next waiter @waiters.shift << true unless @waiters.empty? end end if timeout !!signaled else self end ensure Rubinius.unlock(self) end end |