diff options
author | Matthew Draper <matthew@trebex.net> | 2015-07-09 04:33:14 +0930 |
---|---|---|
committer | Matthew Draper <matthew@trebex.net> | 2015-07-09 04:33:14 +0930 |
commit | 0b93c48bbe74857ead9a9ef56b35f87965edbb49 (patch) | |
tree | 1861b4f1710fda3a66a8eedd94ae8e6cec44fc18 /activesupport/lib/active_support/concurrency | |
parent | 48a735aff7032afaf5534613b10c635acead042a (diff) | |
download | rails-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.rb | 20 |
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) |