116 lines
2.7 KiB
Ruby
116 lines
2.7 KiB
Ruby
require 'concurrent/synchronization'
|
|
require 'concurrent/utility/native_integer'
|
|
|
|
module Concurrent
|
|
|
|
# @!macro semaphore
|
|
# @!visibility private
|
|
# @!macro internal_implementation_note
|
|
class MutexSemaphore < Synchronization::LockableObject
|
|
|
|
# @!macro semaphore_method_initialize
|
|
def initialize(count)
|
|
Utility::NativeInteger.ensure_integer_and_bounds count
|
|
|
|
super()
|
|
synchronize { ns_initialize count }
|
|
end
|
|
|
|
# @!macro semaphore_method_acquire
|
|
def acquire(permits = 1)
|
|
Utility::NativeInteger.ensure_integer_and_bounds permits
|
|
Utility::NativeInteger.ensure_positive permits
|
|
|
|
synchronize do
|
|
try_acquire_timed(permits, nil)
|
|
nil
|
|
end
|
|
end
|
|
|
|
# @!macro semaphore_method_available_permits
|
|
def available_permits
|
|
synchronize { @free }
|
|
end
|
|
|
|
# @!macro semaphore_method_drain_permits
|
|
#
|
|
# Acquires and returns all permits that are immediately available.
|
|
#
|
|
# @return [Integer]
|
|
def drain_permits
|
|
synchronize do
|
|
@free.tap { |_| @free = 0 }
|
|
end
|
|
end
|
|
|
|
# @!macro semaphore_method_try_acquire
|
|
def try_acquire(permits = 1, timeout = nil)
|
|
Utility::NativeInteger.ensure_integer_and_bounds permits
|
|
Utility::NativeInteger.ensure_positive permits
|
|
|
|
synchronize do
|
|
if timeout.nil?
|
|
try_acquire_now(permits)
|
|
else
|
|
try_acquire_timed(permits, timeout)
|
|
end
|
|
end
|
|
end
|
|
|
|
# @!macro semaphore_method_release
|
|
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
|
|
|
|
# Shrinks the number of available permits by the indicated reduction.
|
|
#
|
|
# @param [Fixnum] reduction Number of permits to remove.
|
|
#
|
|
# @raise [ArgumentError] if `reduction` is not an integer or is negative
|
|
#
|
|
# @raise [ArgumentError] if `@free` - `@reduction` is less than zero
|
|
#
|
|
# @return [nil]
|
|
#
|
|
# @!visibility private
|
|
def reduce_permits(reduction)
|
|
Utility::NativeInteger.ensure_integer_and_bounds reduction
|
|
Utility::NativeInteger.ensure_positive reduction
|
|
|
|
synchronize { @free -= reduction }
|
|
nil
|
|
end
|
|
|
|
protected
|
|
|
|
# @!visibility private
|
|
def ns_initialize(count)
|
|
@free = count
|
|
end
|
|
|
|
private
|
|
|
|
# @!visibility private
|
|
def try_acquire_now(permits)
|
|
if @free >= permits
|
|
@free -= permits
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
# @!visibility private
|
|
def try_acquire_timed(permits, timeout)
|
|
ns_wait_until(timeout) { try_acquire_now(permits) }
|
|
end
|
|
end
|
|
end
|