Counting semaphore for concurrent access control with timeouts
gem install philiprehberger-semaphoreCounting semaphore for concurrent access control with timeouts
Add to your Gemfile:
gem "philiprehberger-semaphore"
Or install directly:
gem install philiprehberger-semaphore
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 3)
sem.acquire { do_work }
require "philiprehberger/semaphore"
result = sem.try_acquire(timeout: 5) do
perform_database_query
end
# result is false if timeout expired
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 10)
sem.acquire(weight: 3) { heavy_operation }
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 5, fair: true)
sem.acquire { do_work }
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 3)
sem.resize(5)
sem.permits # => 5
sem.available # => 5
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 3)
# Workers acquire permits in other threads...
# When shutting down, drain blocks until all permits are returned:
sem.drain
# After drain, new acquisitions are rejected:
sem.acquire # => raises Philiprehberger::Semaphore::Error
sem.try_acquire(timeout: 1) # => false
# Or poll non-blockingly: drained? is true once draining AND all permits returned
sem.drained? # => true
require "philiprehberger/semaphore"
sem = Philiprehberger::Semaphore::Counter.new(permits: 5)
sem.acquire
sem.acquire(weight: 2)
sem.acquired_count # => 3
sem.available # => 2
| Method | Description |
|---|---|
.new(permits:, fair: false) | Create a semaphore with the given number of permits and optional FIFO fairness |
#acquire(weight: 1) { block } | Acquire one or more permits, blocking until available |
#try_acquire(timeout:, weight: 1) { block } | Try to acquire within timeout, returns false on expiry |
#release(weight: 1) | Release one or more permits back to the semaphore |
#resize(new_permits) | Change total permit count at runtime |
#drain | Block until all permits are returned; reject new acquisitions |
#available | Return the number of currently available permits |
#acquired_count | Return the number of permits currently held (permits - available) |
#permits | Return the total number of permits |
#fair? | Return whether the semaphore uses FIFO fairness |
#draining? | Return whether the semaphore is currently draining |
#drained? | Return whether the semaphore is draining AND all outstanding permits have been released |
bundle install
bundle exec rspec
bundle exec rubocop
If you find this project useful: