class Concurrent::ReentrantReadWriteLock

def acquire_read_lock

Experimental RBS support (using type sampling data from the type_fusion project).

def acquire_read_lock: () -> true

This signature was generated using 1 sample from 1 application.

Raises:
  • (Concurrent::ResourceLimitError) - if the maximum number of readers

Returns:
  • (Boolean) - true if the lock is successfully acquired
def acquire_read_lock
  if (held = @HeldCount.value) > 0
    # If we already have a lock, there's no need to wait
    if held & READ_LOCK_MASK == 0
      # But we do need to update the counter, if we were holding a write
      #   lock but not a read lock
      @Counter.update { |c| c + 1 }
    end
    @HeldCount.value = held + 1
    return true
  end
  while true
    c = @Counter.value
    raise ResourceLimitError.new('Too many reader threads') if max_readers?(c)
    # If a writer is waiting OR running when we first queue up, we need to wait
    if waiting_or_running_writer?(c)
      # Before going to sleep, check again with the ReadQueue mutex held
      @ReadQueue.synchronize do
        @ReadQueue.ns_wait if waiting_or_running_writer?
      end
      # Note: the above 'synchronize' block could have used #wait_until,
      #   but that waits repeatedly in a loop, checking the wait condition
      #   each time it wakes up (to protect against spurious wakeups)
      # But we are already in a loop, which is only broken when we successfully
      #   acquire the lock! So we don't care about spurious wakeups, and would
      #   rather not pay the extra overhead of using #wait_until
      # After a reader has waited once, they are allowed to "barge" ahead of waiting writers
      # But if a writer is *running*, the reader still needs to wait (naturally)
      while true
        c = @Counter.value
        if running_writer?(c)
          @ReadQueue.synchronize do
            @ReadQueue.ns_wait if running_writer?
          end
        elsif @Counter.compare_and_set(c, c+1)
          @HeldCount.value = held + 1
          return true
        end
      end
    elsif @Counter.compare_and_set(c, c+1)
      @HeldCount.value = held + 1
      return true
    end
  end
end