1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
require 'concurrent/synchronization/lockable_object'
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)
end
return unless block_given?
begin
yield
ensure
release(permits)
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
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
# @!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
|