class ActiveSupport::Concurrency::ShareLock  
        
        A share/exclusive lock, otherwise known as a read/write lock.
Inherits From
- 
          module
          
MonitorMixin 
Public class methods
Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 49
def initialize
  super()
  @cv = new_cond
  @sharing = Hash.new(0)
  @waiting = {}
  @sleeping = {}
  @exclusive_thread = nil
  @exclusive_depth = 0
end
            Public instance methods
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.
See start_exclusive for other options.
Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 147
def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
  if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
    begin
      yield
    ensure
      stop_exclusive(compatible: after_compatible)
    end
  end
end
            Execute the supplied block while holding the Share lock.
Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 158
def sharing
  start_sharing
  begin
    yield
  ensure
    stop_sharing
  end
end
            Returns false if no_wait is set and the lock is not immediately available. Otherwise, returns true after the lock has been acquired.
purpose and compatible work together; while this thread is waiting for the exclusive lock, it will yield its share (if any) to any other attempt whose purpose appears in this attempt’s compatible list. This allows a “loose” upgrade, which, being less strict, prevents some classes of deadlocks.
For many resources, loose upgrades are sufficient: if a thread is awaiting a lock, it is not running any other code. With purpose matching, it is possible to yield only to other threads whose activity will not interfere.
Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 75
def start_exclusive(purpose: nil, compatible: [], no_wait: false)
  synchronize do
    unless @exclusive_thread == Thread.current
      if busy_for_exclusive?(purpose)
        return false if no_wait
        yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
          wait_for(:start_exclusive) { busy_for_exclusive?(purpose) }
        end
      end
      @exclusive_thread = Thread.current
    end
    @exclusive_depth += 1
    true
  end
end
            Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 113
def start_sharing
  synchronize do
    if @sharing[Thread.current] > 0 || @exclusive_thread == Thread.current
      # We already hold a lock; nothing to wait for
    elsif @waiting[Thread.current]
      # We're nested inside a +yield_shares+ call: we'll resume as
      # soon as there isn't an exclusive lock in our way
      wait_for(:start_sharing) { @exclusive_thread }
    else
      # This is an initial / outermost share call: any outstanding
      # requests for an exclusive lock get to go first
      wait_for(:start_sharing) { busy_for_sharing?(false) }
    end
    @sharing[Thread.current] += 1
  end
end
            Relinquish the exclusive lock. Must only be called by the thread that called start_exclusive (and currently holds the lock).
Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 95
def stop_exclusive(compatible: [])
  synchronize do
    raise "invalid unlock" if @exclusive_thread != Thread.current
    @exclusive_depth -= 1
    if @exclusive_depth == 0
      @exclusive_thread = nil
      if eligible_waiters?(compatible)
        yield_shares(compatible: compatible, block_share: true) do
          wait_for(:stop_exclusive) { @exclusive_thread || eligible_waiters?(compatible) }
        end
      end
      @cv.broadcast
    end
  end
end
            Source code GitHub
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 130
def stop_sharing
  synchronize do
    if @sharing[Thread.current] > 1
      @sharing[Thread.current] -= 1
    else
      @sharing.delete Thread.current
      @cv.broadcast
    end
  end
end