123456789_123456789_123456789_123456789_123456789_

Class: Concurrent::MutexSemaphore

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Instance Chain:
Inherits: Concurrent::Synchronization::LockableObject
Defined in: lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb

Overview

Note:

**Private Implementation:** This abstraction is a private, internal implementation detail. It should never be used directly.

A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each #acquire blocks if necessary until a permit is available, and then takes it. Each #release adds a permit, potentially releasing a blocking acquirer. However, no actual permit objects are used; the Semaphore just keeps a count of the number available and acts accordingly. Alternatively, permits may be acquired within a block, and automatically released after the block finishes executing.

Class Method Summary

Instance Method Summary

Synchronization::LockableObject - Inherited

Constructor Details

.new(count) ⇒ MutexSemaphore

Create a new Semaphore with the initial count.

Parameters:

  • count (Fixnum)

    the initial count

Raises:

  • (ArgumentError)

    if count is not an integer

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 12

def initialize(count)
  Utility::NativeInteger.ensure_integer_and_bounds count

  super()
  synchronize { ns_initialize count }
end

Instance Method Details

#acquire(permits = 1) ⇒ nil, BasicObject

Acquires the given number of permits from this semaphore,

blocking until all are available. If a block is given,
yields to it and releases the permits afterwards.

is given, its return value is returned.

Parameters:

  • permits (Fixnum) (defaults to: 1)

    Number of permits to acquire

Returns:

  • (nil, BasicObject)

    Without a block, nil is returned. If a block

Raises:

  • (ArgumentError)

    if permits is not an integer or is less than zero

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 20

def acquire(permits = 1)
  Utility::NativeInteger.ensure_integer_and_bounds permits
  Utility::NativeInteger.ensure_positive permits

  synchronize do
    try_acquire_timed(permits, nil)
  end

  return unless block_given?

  begin
    yield
  ensure
    release(permits)
  end
end

#available_permitsInteger

Returns the current number of permits available in this semaphore.

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 38

def available_permits
  synchronize { @free }
end

#drain_permitsInteger

Acquires and returns all permits that are immediately available.

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 47

def drain_permits
  synchronize do
    @free.tap { |_| @free = 0 }
  end
end

#ns_initialize(count) (private)

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 110

def ns_initialize(count)
  @free = count
end

#reduce_permits(reduction) ⇒ nil (private)

Shrinks the number of available permits by the indicated reduction.

Parameters:

  • reduction (Fixnum)

    Number of permits to remove.

Raises:

  • (ArgumentError)

    if reduction is not an integer or is negative

  • (ArgumentError)

    if @free - @reduction is less than zero

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 99

def reduce_permits(reduction)
  Utility::NativeInteger.ensure_integer_and_bounds reduction
  Utility::NativeInteger.ensure_positive reduction

  synchronize { @free -= reduction }
  nil
end

#release(permits = 1) ⇒ nil

Releases the given number of permits, returning them to the semaphore.

Parameters:

  • permits (Fixnum) (defaults to: 1)

    Number of permits to return to the semaphore.

Raises:

  • (ArgumentError)

    if permits is not a number or is less than zero

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 77

def release(permits = 1)
  Utility::NativeInteger.ensure_integer_and_bounds permits
  Utility::NativeInteger.ensure_positive permits

  synchronize do
    @free += permits
    permits.times { ns_signal }
  end
  nil
end

#try_acquire(permits = 1, timeout = nil) ⇒ true, ...

Acquires the given number of permits from this semaphore,

only if all are available at the time of invocation or within
{timeout} interval. If a block is given, yields to it if the permits
were successfully acquired, and releases them afterward, returning the
block's return value.

Parameters:

  • permits (Fixnum) (defaults to: 1)

    the number of permits to acquire

  • timeout (Fixnum) (defaults to: nil)

    the number of seconds to wait for the counter or nil to return immediately

Returns:

  • (true, false, nil, BasicObject)

    false if no permits are available, true when acquired a permit. If a block is given, the block’s return value is returned if the permits were acquired; if not, nil is returned.

Raises:

  • (ArgumentError)

    if permits is not an integer or is less than zero

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 54

def try_acquire(permits = 1, timeout = nil)
  Utility::NativeInteger.ensure_integer_and_bounds permits
  Utility::NativeInteger.ensure_positive permits

  acquired = synchronize do
    if timeout.nil?
      try_acquire_now(permits)
    else
      try_acquire_timed(permits, timeout)
    end
  end

  return acquired unless block_given?
  return unless acquired

  begin
    yield
  ensure
    release(permits)
  end
end

#try_acquire_now(permits) (private)

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 117

def try_acquire_now(permits)
  if @free >= permits
    @free -= permits
    true
  else
    false
  end
end

#try_acquire_timed(permits, timeout) (private)

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb', line 127

def try_acquire_timed(permits, timeout)
  ns_wait_until(timeout) { try_acquire_now(permits) }
end