pub struct Semaphore { /* private fields */ }Expand description
A counting semaphore whose waits are futures.
A request for n permits takes them whenever n are free, even while
others wait; under contention acquire_many
queues. A release wakes the oldest waiters the freed permits could
serve, stopping at the first that does not fit, so a large request at
the front is not skipped for smaller ones behind it. A waiter that
loses MAX_BYPASS times is owed a handoff: until
it is served, try_acquire fails and releases go
to the waiters in queue order.
close ends every wait with an AcquireError and makes
later acquires fail at once.
use nuclei::sync::{Semaphore, TryAcquireError};
let budget = Semaphore::new(4);
let first = budget.try_acquire_many(3).expect("three of four are free");
assert_eq!(budget.try_acquire_many(2).unwrap_err(), TryAcquireError::NoPermits);
drop(first);
assert_eq!(budget.available_permits(), 4);Implementations§
Source§impl Semaphore
impl Semaphore
Sourcepub const MAX_PERMITS: usize = MAX
pub const MAX_PERMITS: usize = MAX
The most permits a semaphore can hold: usize::MAX >> 7. The state
word keeps seven low bits for the wait queue and the closed flag, so
this is 2^57 - 1 on a 64-bit target and 2^25 - 1 on a 32-bit one.
Sourcepub fn available_permits(&self) -> usize
pub fn available_permits(&self) -> usize
The permits free right now.
Sourcepub fn add_permits(&self, n: usize)
pub fn add_permits(&self, n: usize)
Adds n new permits, handing them to waiters first. It makes the
progress a returned permit does (see SemaphorePermit). Permits
added to a closed semaphore are counted, but nothing is handed out.
§Panics
When the semaphore would hold more than
MAX_PERMITS.
Sourcepub fn forget_permits(&self, n: usize) -> usize
pub fn forget_permits(&self, n: usize) -> usize
Removes up to n free permits for good and returns how many it
removed, which is fewer than n when fewer are free. Permits held by
outstanding SemaphorePermits are not touched.
Sourcepub fn acquire(&self) -> Acquire<'_> ⓘ
pub fn acquire(&self) -> Acquire<'_> ⓘ
Waits for one permit. Uncontended, the first poll is one atomic read-modify-write. Contended, it is lock-free, not wait-free: see Progress.
Completes with an AcquireError once the semaphore is
closed.
Sourcepub fn acquire_many(&self, n: u32) -> Acquire<'_> ⓘ
pub fn acquire_many(&self, n: u32) -> Acquire<'_> ⓘ
Waits for n permits, which it takes together.
Completes with an AcquireError once the semaphore is
closed.
§Panics
When n exceeds MAX_PERMITS, which only a
target with a word narrower than 64 bits allows and which no
semaphore can ever satisfy.
Sourcepub fn acquire_owned(self: Arc<Self>) -> AcquireOwned ⓘ
pub fn acquire_owned(self: Arc<Self>) -> AcquireOwned ⓘ
Waits for one permit through an Arc, so the permit can outlive the
borrow.
Completes with an AcquireError once the semaphore is
closed.
Sourcepub fn acquire_many_owned(self: Arc<Self>, n: u32) -> AcquireOwned ⓘ
pub fn acquire_many_owned(self: Arc<Self>, n: u32) -> AcquireOwned ⓘ
Waits for n permits through an Arc, so the permits can outlive
the borrow.
§Panics
When n exceeds MAX_PERMITS, as for
acquire_many.
Sourcepub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>
pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>
Takes one permit if it is free and no handoff is owed.
Sourcepub fn try_acquire_many(
&self,
n: u32,
) -> Result<SemaphorePermit<'_>, TryAcquireError>
pub fn try_acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, TryAcquireError>
Takes n permits together if they are free and no handoff is owed.
§Panics
When n exceeds MAX_PERMITS, as for
acquire_many.
Sourcepub fn try_acquire_owned(
self: Arc<Self>,
) -> Result<OwnedSemaphorePermit, TryAcquireError>
pub fn try_acquire_owned( self: Arc<Self>, ) -> Result<OwnedSemaphorePermit, TryAcquireError>
Takes one permit through an Arc if it is free and no handoff is
owed.
Sourcepub fn try_acquire_many_owned(
self: Arc<Self>,
n: u32,
) -> Result<OwnedSemaphorePermit, TryAcquireError>
pub fn try_acquire_many_owned( self: Arc<Self>, n: u32, ) -> Result<OwnedSemaphorePermit, TryAcquireError>
Takes n permits together through an Arc if they are free and no
handoff is owed.
§Panics
When n exceeds MAX_PERMITS, as for
acquire_many.
Sourcepub fn blocking_acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError>
pub fn blocking_acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError>
acquire for a thread that may block: it parks the
calling thread until the permit is free. On a nuclei shard (inside one of its tasks) it does not park the thread: it runs a nested block_on, so the shard keeps running its other tasks meanwhile.
Inside another runtime’s task it blocks that task’s executor thread,
so do not.
§Panics
On wasm32, where no other thread can return a permit, when the
permit is not free: the call could never end.
Sourcepub fn blocking_acquire_many(
&self,
n: u32,
) -> Result<SemaphorePermit<'_>, AcquireError>
pub fn blocking_acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, AcquireError>
acquire_many for a thread that may block: see
blocking_acquire.
§Panics
As for blocking_acquire, and when n
exceeds MAX_PERMITS.
Sourcepub fn blocking_acquire_owned(
self: Arc<Self>,
) -> Result<OwnedSemaphorePermit, AcquireError>
pub fn blocking_acquire_owned( self: Arc<Self>, ) -> Result<OwnedSemaphorePermit, AcquireError>
Sourcepub fn blocking_acquire_many_owned(
self: Arc<Self>,
n: u32,
) -> Result<OwnedSemaphorePermit, AcquireError>
pub fn blocking_acquire_many_owned( self: Arc<Self>, n: u32, ) -> Result<OwnedSemaphorePermit, AcquireError>
acquire_many_owned for a thread that may
block: see blocking_acquire.
§Panics
As for blocking_acquire, and when n
exceeds MAX_PERMITS.
Sourcepub fn close(&self)
pub fn close(&self)
Closes the semaphore. Every wait still queued ends in an
AcquireError, and every later acquire fails at once: try_acquire
and its siblings return TryAcquireError::Closed, whatever permits
are free. A wait that was handed its permits before the close keeps
them. Permits returned or added afterwards are counted, and
available_permits shows them, but none is
ever handed out. Closing twice does nothing.
It makes the progress a returned permit does (see
SemaphorePermit).