aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/share_lock_test.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-02-01 23:41:07 +1030
committerMatthew Draper <matthew@trebex.net>2016-02-02 03:21:03 +1030
commitaeb58ab70470b7f395a1e77b10c9b7a73955dad8 (patch)
tree6ecf496f8abe16c56716f590087d9a8fdaeb8337 /activesupport/test/share_lock_test.rb
parent92203edbe6546f84921b6ccb6e79c3a01857a8b3 (diff)
downloadrails-aeb58ab70470b7f395a1e77b10c9b7a73955dad8.tar.gz
rails-aeb58ab70470b7f395a1e77b10c9b7a73955dad8.tar.bz2
rails-aeb58ab70470b7f395a1e77b10c9b7a73955dad8.zip
Block new share attempts if there's an exclusive waiter
Diffstat (limited to 'activesupport/test/share_lock_test.rb')
-rw-r--r--activesupport/test/share_lock_test.rb32
1 files changed, 32 insertions, 0 deletions
diff --git a/activesupport/test/share_lock_test.rb b/activesupport/test/share_lock_test.rb
index 465a657308..0a5b074bee 100644
--- a/activesupport/test/share_lock_test.rb
+++ b/activesupport/test/share_lock_test.rb
@@ -114,14 +114,17 @@ class ShareLockTest < ActiveSupport::TestCase
[true, false].each do |use_upgrading|
with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
begin
+ together = Concurrent::CyclicBarrier.new(2)
conflicting_exclusive_threads = [
Thread.new do
@lock.send(use_upgrading ? :sharing : :tap) do
+ together.wait
@lock.exclusive(purpose: :red, compatible: [:green, :purple]) {}
end
end,
Thread.new do
@lock.send(use_upgrading ? :sharing : :tap) do
+ together.wait
@lock.exclusive(purpose: :blue, compatible: [:green]) {}
end
end
@@ -183,11 +186,14 @@ class ShareLockTest < ActiveSupport::TestCase
load_params = [:load, [:load]]
unload_params = [:unload, [:unload, :load]]
+ all_sharing = Concurrent::CyclicBarrier.new(4)
+
[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
+ all_sharing.wait
@lock.exclusive(purpose: purpose, compatible: compatible) do
scratch_pad_mutex.synchronize { scratch_pad << purpose }
end
@@ -209,6 +215,32 @@ class ShareLockTest < ActiveSupport::TestCase
end
end
+ def test_new_share_attempts_block_on_waiting_exclusive
+ with_thread_waiting_in_lock_section(:sharing) do |sharing_thread_release_latch|
+ release_exclusive = Concurrent::CountDownLatch.new
+
+ waiting_exclusive = Thread.new do
+ @lock.sharing do
+ @lock.exclusive do
+ release_exclusive.wait
+ end
+ end
+ end
+ assert_threads_stuck waiting_exclusive
+
+ late_share_attempt = Thread.new do
+ @lock.sharing {}
+ end
+ assert_threads_stuck late_share_attempt
+
+ sharing_thread_release_latch.count_down
+ assert_threads_stuck late_share_attempt
+
+ release_exclusive.count_down
+ assert_threads_not_stuck late_share_attempt
+ end
+ end
+
def test_in_shared_section_incompatible_non_upgrading_threads_cannot_preempt_upgrading_threads
scratch_pad = []
scratch_pad_mutex = Mutex.new