mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@d6921ef
This commit is contained in:
parent
207a5a5bc1
commit
a6c6eef04a
44 changed files with 1141 additions and 250 deletions
175
spec/ruby/core/conditionvariable/wait_spec.rb
Normal file
175
spec/ruby/core/conditionvariable/wait_spec.rb
Normal file
|
@ -0,0 +1,175 @@
|
|||
require_relative '../../spec_helper'
|
||||
require 'thread'
|
||||
|
||||
describe "ConditionVariable#wait" do
|
||||
it "calls #sleep on the given object" do
|
||||
o = Object.new
|
||||
o.should_receive(:sleep).with(1234)
|
||||
|
||||
cv = ConditionVariable.new
|
||||
|
||||
cv.wait(o, 1234)
|
||||
end
|
||||
|
||||
it "can be woken up by ConditionVariable#signal" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
cv.wait(m)
|
||||
end
|
||||
:success
|
||||
end
|
||||
|
||||
# wait for m to acquire the mutex
|
||||
Thread.pass until in_synchronize
|
||||
# wait until th is sleeping (ie waiting)
|
||||
Thread.pass until th.stop?
|
||||
|
||||
m.synchronize { cv.signal }
|
||||
th.value.should == :success
|
||||
end
|
||||
|
||||
it "can be interrupted by Thread#run" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
cv.wait(m)
|
||||
end
|
||||
:success
|
||||
end
|
||||
|
||||
# wait for m to acquire the mutex
|
||||
Thread.pass until in_synchronize
|
||||
# wait until th is sleeping (ie waiting)
|
||||
Thread.pass until th.stop?
|
||||
|
||||
th.run
|
||||
th.value.should == :success
|
||||
end
|
||||
|
||||
it "can be interrupted by Thread#wakeup" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
cv.wait(m)
|
||||
end
|
||||
:success
|
||||
end
|
||||
|
||||
# wait for m to acquire the mutex
|
||||
Thread.pass until in_synchronize
|
||||
# wait until th is sleeping (ie waiting)
|
||||
Thread.pass until th.stop?
|
||||
|
||||
th.wakeup
|
||||
th.value.should == :success
|
||||
end
|
||||
|
||||
it "reacquires the lock even if the thread is killed" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
owned = nil
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
begin
|
||||
cv.wait(m)
|
||||
ensure
|
||||
owned = m.owned?
|
||||
$stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# wait for m to acquire the mutex
|
||||
Thread.pass until in_synchronize
|
||||
# wait until th is sleeping (ie waiting)
|
||||
Thread.pass until th.stop?
|
||||
|
||||
th.kill
|
||||
th.join
|
||||
|
||||
owned.should == true
|
||||
end
|
||||
|
||||
it "reacquires the lock even if the thread is killed after being signaled" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
in_synchronize = false
|
||||
owned = nil
|
||||
|
||||
th = Thread.new do
|
||||
m.synchronize do
|
||||
in_synchronize = true
|
||||
begin
|
||||
cv.wait(m)
|
||||
ensure
|
||||
owned = m.owned?
|
||||
$stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# wait for m to acquire the mutex
|
||||
Thread.pass until in_synchronize
|
||||
# wait until th is sleeping (ie waiting)
|
||||
Thread.pass until th.stop?
|
||||
|
||||
m.synchronize {
|
||||
cv.signal
|
||||
# Wait that the thread is blocked on acquiring the Mutex
|
||||
sleep 0.001
|
||||
# Kill the thread, yet the thread should first acquire the Mutex before going on
|
||||
th.kill
|
||||
}
|
||||
|
||||
th.join
|
||||
owned.should == true
|
||||
end
|
||||
|
||||
it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do
|
||||
m = Mutex.new
|
||||
cv = ConditionVariable.new
|
||||
n_threads = 4
|
||||
events = []
|
||||
|
||||
threads = n_threads.times.map {
|
||||
Thread.new {
|
||||
m.synchronize {
|
||||
events << :t_in_synchronize
|
||||
cv.wait(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Thread.pass until m.synchronize { events.size } == n_threads
|
||||
Thread.pass until threads.any?(&:stop?)
|
||||
m.synchronize do
|
||||
threads.each { |t|
|
||||
# Cause interactions with the waiting threads.
|
||||
# On TruffleRuby, this causes a safepoint which has interesting
|
||||
# interactions with the ConditionVariable.
|
||||
bt = t.backtrace
|
||||
bt.should be_kind_of(Array)
|
||||
bt.size.should >= 2
|
||||
}
|
||||
end
|
||||
|
||||
cv.broadcast
|
||||
threads.each(&:join)
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue