1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 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 84 85 86 87 88 89 90
|
require "../spec_helper"
# interpreter doesn't support threads yet (#14287)
pending_interpreted describe: Thread::ConditionVariable do
it "signals" do
mutex = Thread::Mutex.new
cond = Thread::ConditionVariable.new
mutex.synchronize do
Thread.new do
mutex.synchronize { cond.signal }
end
cond.wait(mutex)
end
end
it "signals & broadcasts" do
mutex = Thread::Mutex.new
cv1 = Thread::ConditionVariable.new
cv2 = Thread::ConditionVariable.new
waiting = 0
5.times do
Thread.new do
mutex.synchronize do
waiting += 1
cv1.wait(mutex)
waiting -= 1
cv2.signal
end
end
end
# wait for all threads to have acquired the mutex and be waiting on the
# condition variable, otherwise the main thread could acquire the lock
# first, and signal into the void.
#
# since increments to waiting are synchronized, at least 4 threads are
# guaranteed to be waiting when waiting is 5, which is enough for further
# tests to never hangup.
until waiting == 5
Thread.yield
end
# wakes up at least 1 thread:
mutex.synchronize do
cv1.signal
cv2.wait(mutex)
end
waiting.should be < 5
# wakes up all waiting threads:
mutex.synchronize do
cv1.broadcast
until waiting == 0
cv2.wait(mutex, 1.second) { raise "unexpected wait timeout" }
end
end
end
it "timeouts" do
timedout = false
mutex = Thread::Mutex.new
cond = Thread::ConditionVariable.new
mutex.synchronize do
cond.wait(mutex, 1.microsecond) { timedout = true }
end
timedout.should be_true
end
it "resumes before timeout" do
timedout = false
mutex = Thread::Mutex.new
cond = Thread::ConditionVariable.new
mutex.synchronize do
Thread.new do
mutex.synchronize { cond.signal }
end
cond.wait(mutex, 1.second) { timedout = true }
end
timedout.should be_false
end
end
|