class Concurrent::Semaphore

@!macro semaphore

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.

@!macro semaphore_public_api @example

semaphore = Concurrent::Semaphore.new(2)

t1 = Thread.new do
  semaphore.acquire
  puts "Thread 1 acquired semaphore"
end

t2 = Thread.new do
  semaphore.acquire
  puts "Thread 2 acquired semaphore"
end

t3 = Thread.new do
  semaphore.acquire
  puts "Thread 3 acquired semaphore"
end

t4 = Thread.new do
  sleep(2)
  puts "Thread 4 releasing semaphore"
  semaphore.release
end

[t1, t2, t3, t4].each(&:join)

# prints:
# Thread 3 acquired semaphore
# Thread 2 acquired semaphore
# Thread 4 releasing semaphore
# Thread 1 acquired semaphore

@example

semaphore = Concurrent::Semaphore.new(1)

puts semaphore.available_permits
semaphore.acquire do
  puts semaphore.available_permits
end
puts semaphore.available_permits

# prints:
# 1
# 0
# 1