aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/concurrency
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2015-07-09 04:33:14 +0930
committerMatthew Draper <matthew@trebex.net>2015-07-09 04:33:14 +0930
commit0b93c48bbe74857ead9a9ef56b35f87965edbb49 (patch)
tree1861b4f1710fda3a66a8eedd94ae8e6cec44fc18 /activesupport/lib/active_support/concurrency
parent48a735aff7032afaf5534613b10c635acead042a (diff)
downloadrails-0b93c48bbe74857ead9a9ef56b35f87965edbb49.tar.gz
rails-0b93c48bbe74857ead9a9ef56b35f87965edbb49.tar.bz2
rails-0b93c48bbe74857ead9a9ef56b35f87965edbb49.zip
Document ShareLock and the Interlock
Diffstat (limited to 'activesupport/lib/active_support/concurrency')
-rw-r--r--activesupport/lib/active_support/concurrency/share_lock.rb20
1 files changed, 20 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/concurrency/share_lock.rb b/activesupport/lib/active_support/concurrency/share_lock.rb
index e03f2cfc7a..f1c6230084 100644
--- a/activesupport/lib/active_support/concurrency/share_lock.rb
+++ b/activesupport/lib/active_support/concurrency/share_lock.rb
@@ -3,6 +3,15 @@ require 'monitor'
module ActiveSupport
module Concurrency
+ # A share/exclusive lock, otherwise known as a read/write lock.
+ #
+ # https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
+ #--
+ # Note that a pending Exclusive lock attempt does not block incoming
+ # Share requests (i.e., we are "read-preferring"). That seems
+ # consistent with the behavior of +loose_upgrades+, but may be the
+ # wrong choice otherwise: it nominally reduces the possibility of
+ # deadlock by risking starvation instead.
class ShareLock
include MonitorMixin
@@ -35,6 +44,9 @@ module ActiveSupport
@exclusive_depth = 0
end
+ # Returns false if +no_wait+ is specified and the lock is not
+ # immediately available. Otherwise, returns true after the lock
+ # has been acquired.
def start_exclusive(no_wait=false)
synchronize do
unless @exclusive_thread == Thread.current
@@ -56,6 +68,8 @@ module ActiveSupport
end
end
+ # Relinquish the exclusive lock. Must only be called by the thread
+ # that called start_exclusive (and currently holds the lock).
def stop_exclusive
synchronize do
raise "invalid unlock" if @exclusive_thread != Thread.current
@@ -88,6 +102,10 @@ module ActiveSupport
end
end
+ # Execute the supplied block while holding the Exclusive lock. If
+ # +no_wait+ is set and the lock is not immediately available,
+ # returns +nil+ without yielding. Otherwise, returns the result of
+ # the block.
def exclusive(no_wait=false)
if start_exclusive(no_wait)
begin
@@ -98,6 +116,7 @@ module ActiveSupport
end
end
+ # Execute the supplied block while holding the Share lock.
def sharing
start_sharing
begin
@@ -109,6 +128,7 @@ module ActiveSupport
private
+ # Must be called within synchronize
def busy?
(@exclusive_thread && @exclusive_thread != Thread.current) ||
@sharing.size > (@sharing[Thread.current] > 0 ? 1 : 0)