class Synapse::DisposableLock

@api private

Attributes

closed[R]

@return [Boolean]

closed?[R]

@return [Boolean]

owner[R]

@return [Thread]

waiters[R]

@return [Array]

Public Class Methods

new() click to toggle source

@return [undefined]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 16
def initialize
  @mutex = Mutex.new

  @closed = false
  @hold_count = 0
  @owner = nil
  @waiters = Array.new
end

Public Instance Methods

lock() click to toggle source

@return [Boolean] False if lock has been closed

# File lib/synapse/common/concurrency/disposable_lock.rb, line 42
def lock
  @mutex.synchronize do
    unless owned?
      if @hold_count == 0
        @owner = Thread.current
      else
        @waiters.push Thread.current

        begin
          wait_for_lock
        ensure
          @waiters.delete Thread.current
        end

        return unless owned?
      end
    end

    @hold_count += 1
  end

  if closed?
    unlock
    return false
  end

  return true
end
locked?() click to toggle source

@return [Boolean]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 37
def locked?
  @hold_count > 0
end
owned?() click to toggle source

@return [Boolean]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 26
def owned?
  @owner == Thread.current
end
owned_by?(thread) click to toggle source

@param [Thread] thread @return [Boolean]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 32
def owned_by?(thread)
  @owner == thread
end
try_close() click to toggle source

@return [Boolean] True if lock was closed

# File lib/synapse/common/concurrency/disposable_lock.rb, line 103
def try_close
  return false unless try_lock

  begin
    if @hold_count == 1
      @closed = true
      return true
    end

    return false
  ensure
    unlock
  end
end
try_lock() click to toggle source

@return [Boolean]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 72
def try_lock
  @mutex.synchronize do
    unless owned?
      if @hold_count == 0
        @owner = Thread.current
      else
        return false
      end
    end

    @hold_count += 1
    return true
  end
end
unlock() click to toggle source

@raise [RuntimeError] If caller does not own the lock @return [undefined]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 89
def unlock
  @mutex.synchronize do
    raise RuntimeError unless owned?

    @hold_count -= 1

    if @hold_count == 0
      @owner = nil
      wakeup_next_waiter
    end
  end
end

Private Instance Methods

check_for_deadlock() click to toggle source

@raise [DeadlockError] @return [undefined]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 122
def check_for_deadlock
  return if owned?
  return unless locked?

  for waiter in IdentifierLockManager.waiters_for_locks_owned_by(Thread.current)
    if owned_by? waiter
      raise DeadlockError
    end
  end
end
wait_for_lock() click to toggle source

Mutex must be locked to perform this operation @return [undefined]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 135
def wait_for_lock
  loop do
    if @hold_count == 0
      @owner = Thread.current
      return
    end

    check_for_deadlock
    @mutex.sleep 0.1 # Sleep for 100 milliseconds
  end
end
wakeup_next_waiter() click to toggle source

@return [undefined]

# File lib/synapse/common/concurrency/disposable_lock.rb, line 148
def wakeup_next_waiter
  begin
    n = @waiters.shift
    n.wakeup if n
  rescue ThreadError
    retry
  end
end