Small tweaks to mainly lock-ordering tests.
* only test the upgrade path, * add test to verify non upgrades can’t preempt, * add reentrancy assertion.
This commit is contained in:
parent
e9020ac431
commit
5d6770754e
@ -7,6 +7,14 @@ def setup
|
||||
@lock = ActiveSupport::Concurrency::ShareLock.new
|
||||
end
|
||||
|
||||
def test_reentrancy
|
||||
thread = Thread.new do
|
||||
@lock.sharing { @lock.sharing {} }
|
||||
@lock.exclusive { @lock.exclusive {} }
|
||||
end
|
||||
assert_threads_not_stuck thread
|
||||
end
|
||||
|
||||
def test_sharing_doesnt_block
|
||||
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_latch|
|
||||
assert_threads_not_stuck(Thread.new {@lock.sharing {} })
|
||||
@ -169,38 +177,67 @@ def test_exclusive_conflicting_purpose
|
||||
end
|
||||
|
||||
def test_exclusive_ordering
|
||||
[true, false].each do |use_upgrading|
|
||||
scratch_pad = []
|
||||
scratch_pad_mutex = Mutex.new
|
||||
scratch_pad = []
|
||||
scratch_pad_mutex = Mutex.new
|
||||
|
||||
load_params = [:load, [:load]]
|
||||
unload_params = [:unload, [:unload, :load]]
|
||||
load_params = [:load, [:load]]
|
||||
unload_params = [:unload, [:unload, :load]]
|
||||
|
||||
[load_params, load_params, unload_params, unload_params].permutation do |thread_params|
|
||||
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
|
||||
threads = thread_params.map do |purpose, compatible|
|
||||
Thread.new do
|
||||
@lock.send(use_upgrading ? :sharing : :tap) do
|
||||
@lock.exclusive(purpose: purpose, compatible: compatible) do
|
||||
scratch_pad_mutex.synchronize { scratch_pad << purpose }
|
||||
end
|
||||
[load_params, load_params, unload_params, unload_params].permutation do |thread_params|
|
||||
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
|
||||
threads = thread_params.map do |purpose, compatible|
|
||||
Thread.new do
|
||||
@lock.sharing do
|
||||
@lock.exclusive(purpose: purpose, compatible: compatible) do
|
||||
scratch_pad_mutex.synchronize { scratch_pad << purpose }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sleep(0.01)
|
||||
scratch_pad_mutex.synchronize { assert_empty scratch_pad }
|
||||
sleep(0.01)
|
||||
scratch_pad_mutex.synchronize { assert_empty scratch_pad }
|
||||
|
||||
sharing_thread_release_latch.count_down
|
||||
sharing_thread_release_latch.count_down
|
||||
|
||||
assert_threads_not_stuck threads
|
||||
scratch_pad_mutex.synchronize do
|
||||
if use_upgrading
|
||||
assert_equal [:load, :load, :unload, :unload], scratch_pad
|
||||
assert_threads_not_stuck threads
|
||||
scratch_pad_mutex.synchronize do
|
||||
assert_equal [:load, :load, :unload, :unload], scratch_pad
|
||||
scratch_pad.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_in_shared_section_incompatible_non_upgrading_threads_cannot_preempt_upgrading_threads
|
||||
scratch_pad = []
|
||||
scratch_pad_mutex = Mutex.new
|
||||
|
||||
upgrading_load_params = [:load, [:load], true]
|
||||
non_upgrading_unload_params = [:unload, [:load, :unload], false]
|
||||
|
||||
[upgrading_load_params, non_upgrading_unload_params].permutation do |thread_params|
|
||||
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
|
||||
threads = thread_params.map do |purpose, compatible, use_upgrading|
|
||||
Thread.new do
|
||||
@lock.send(use_upgrading ? :sharing : :tap) do
|
||||
@lock.exclusive(purpose: purpose, compatible: compatible) do
|
||||
scratch_pad_mutex.synchronize { scratch_pad << purpose }
|
||||
end
|
||||
end
|
||||
scratch_pad.clear
|
||||
end
|
||||
end
|
||||
|
||||
assert_threads_stuck threads
|
||||
scratch_pad_mutex.synchronize { assert_empty scratch_pad }
|
||||
|
||||
sharing_thread_release_latch.count_down
|
||||
|
||||
assert_threads_not_stuck threads
|
||||
scratch_pad_mutex.synchronize do
|
||||
assert_equal [:load, :unload], scratch_pad
|
||||
scratch_pad.clear
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user