class RIMS::ReadWriteLock

Constants

DEFAULT_TIMEOUT_SECONDS

Public Class Methods

new() click to toggle source
# File lib/rims/lock.rb, line 26
def initialize
  @lock = Thread::Mutex.new
  @read_cond = Thread::ConditionVariable.new
  @write_cond = Thread::ConditionVariable.new
  @count_of_working_readers = 0
  @count_of_standby_writers = 0
  @prefer_to_writer = true
  @writing = false
end
write_lock_timeout_detach(first_timeout_seconds, detached_timeout_seconds, logger: Logger.new(STDOUT)) { |timeout_seconds| ... } click to toggle source
# File lib/rims/lock.rb, line 119
def self.write_lock_timeout_detach(first_timeout_seconds, detached_timeout_seconds, logger: Logger.new(STDOUT)) # yields: timeout_seconds
  begin
    logger.debug('ready to detach write-lock timeout.') if logger.debug?
    yield(first_timeout_seconds)
    logger.debug('not detached write-lock timeout.') if logger.debug?
    nil
  rescue WriteLockTimeoutError
    logger.warn($!)
    Thread.new{
      begin
        logger.warn('detached write-lock timeout.')
        yield(detached_timeout_seconds)
        logger.info('detached write-lock timeout thread is completed.')
        nil
      rescue WriteLockTimeoutError
        logger.warn($!)
        retry
      rescue
        logger.error('unexpected error at a detached thread and give up to retry write-lock timeout error.')
        Error.trace_error_chain($!) do |exception|
          logger.error(exception)
        end

        $!
      end
    }
  end
end

Public Instance Methods

read_lock(timeout_seconds=DEFAULT_TIMEOUT_SECONDS) click to toggle source
# File lib/rims/lock.rb, line 36
def read_lock(timeout_seconds=DEFAULT_TIMEOUT_SECONDS)
  time_limit = Time.now + timeout_seconds
  @lock.synchronize{
    while (@writing || (@prefer_to_writer && @count_of_standby_writers > 0))
      if (timeout_seconds > 0) then
        @read_cond.wait(@lock, timeout_seconds)
      else
        raise ReadLockTimeoutError, 'read-lock wait timeout'
      end
      timeout_seconds = time_limit - Time.now
    end
    @count_of_working_readers += 1
  }
  nil
end
read_synchronize(timeout_seconds=DEFAULT_TIMEOUT_SECONDS) { || ... } click to toggle source
# File lib/rims/lock.rb, line 64
def read_synchronize(timeout_seconds=DEFAULT_TIMEOUT_SECONDS)
  read_lock(timeout_seconds)
  begin
    yield
  ensure
    read_unlock
  end
end
read_unlock() click to toggle source
# File lib/rims/lock.rb, line 52
def read_unlock
  @lock.synchronize{
    @count_of_working_readers -= 1
    @count_of_working_readers >= 0 or raise IllegalLockError, 'illegal read lock pattern: lock/unlock/unlock'
    @prefer_to_writer = true
    if (@count_of_standby_writers > 0) then
      @write_cond.signal
    end
  }
  nil
end
synchronize(timeout_seconds=DEFAULT_TIMEOUT_SECONDS)

compatible for Thread::Mutex

Alias for: write_synchronize
write_lock(timeout_seconds=DEFAULT_TIMEOUT_SECONDS) click to toggle source
# File lib/rims/lock.rb, line 73
def write_lock(timeout_seconds=DEFAULT_TIMEOUT_SECONDS)
  time_limit = Time.now + timeout_seconds
  @lock.synchronize{
    @count_of_standby_writers += 1
    begin
      while (@writing || @count_of_working_readers > 0)
        if (timeout_seconds > 0) then
          @write_cond.wait(@lock, timeout_seconds)
        else
          raise WriteLockTimeoutError, 'write-lock wait timeout'
        end
        timeout_seconds = time_limit - Time.now
      end
      @writing = true
    ensure
      @count_of_standby_writers -= 1
    end
  }
  nil
end
write_synchronize(timeout_seconds=DEFAULT_TIMEOUT_SECONDS) { || ... } click to toggle source
# File lib/rims/lock.rb, line 107
def write_synchronize(timeout_seconds=DEFAULT_TIMEOUT_SECONDS)
  write_lock(timeout_seconds)
  begin
    yield
  ensure
    write_unlock
  end
end
Also aliased as: synchronize
write_unlock() click to toggle source
# File lib/rims/lock.rb, line 94
def write_unlock
  @lock.synchronize{
    @writing or raise IllegalLockError, 'illegal write lock pattern: lock/unlock/unlock'
    @writing = false
    @prefer_to_writer = false
    @read_cond.broadcast
    if (@count_of_standby_writers > 0) then
      @write_cond.signal
    end
  }
  nil
end