pub struct Semaphore { /* private fields */ }Expand description
An async counting semaphore for controlling access to a set of resources.
See the module level documentation for more.
Implementations§
Source§impl Semaphore
impl Semaphore
Sourcepub const fn new(permits: usize) -> Self
pub const fn new(permits: usize) -> Self
Creates a new semaphore with the given number of permits.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(5); // Creates a semaphore with 5 permitsSourcepub fn available_permits(&self) -> usize
pub fn available_permits(&self) -> usize
Returns the current number of permits available.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(2);
assert_eq!(sem.available_permits(), 2);
let permit = sem.try_acquire(1).unwrap();
assert_eq!(sem.available_permits(), 1);Sourcepub fn drain_permits(&self, up_to: usize) -> usize
pub fn drain_permits(&self, up_to: usize) -> usize
Atomically drains up to up_to permits that are currently available.
Returns the number of permits actually drained, which may be less than up_to.
This operation neither creates nor cancels a deficit against future releases and does not
affect permits that have already been acquired.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(4);
let held = sem.try_acquire(2).unwrap();
assert_eq!(sem.drain_permits(1), 1);
assert_eq!(sem.available_permits(), 1);
assert_eq!(sem.drain_permits(3), 1);
assert_eq!(sem.available_permits(), 0);
drop(held);
assert_eq!(sem.available_permits(), 2);Sourcepub fn reduce_permits(&self, n: usize)
pub fn reduce_permits(&self, n: usize)
Reduces the semaphore’s logical permit balance by exactly n.
This method returns immediately. If fewer than n permits are currently available, future
releases repay the resulting deficit before ordinary queued acquisitions may proceed.
Permits that have already been acquired remain valid and are not revoked.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(1);
sem.reduce_permits(3); // Consumes 1 available permit and records a deficit of 2.
assert_eq!(sem.available_permits(), 0);
sem.release(2); // Repays the deficit, so neither permit becomes available.
assert_eq!(sem.available_permits(), 0);
sem.release(1); // With the deficit repaid, this permit becomes available.
assert_eq!(sem.available_permits(), 1);Sourcepub fn release(&self, permits: usize)
pub fn release(&self, permits: usize)
Adds n new permits to the semaphore.
§Panics
Panics if adding the permits would overflow the total permit count, or if notifying a waiter panics. Added permits remain available, and notification is still attempted for every other eligible waiter before the panic resumes.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(0);
sem.release(2); // Adds 2 permits
assert_eq!(sem.available_permits(), 2);Sourcepub fn try_acquire(&self, permits: usize) -> Option<SemaphorePermit<'_>>
pub fn try_acquire(&self, permits: usize) -> Option<SemaphorePermit<'_>>
Attempts to acquire n permits from the semaphore without blocking.
If the permits are successfully acquired, a SemaphorePermit is returned.
The permits will be automatically returned to the semaphore when the permit
is dropped, unless forget is called.
§Examples
use asyncband::semaphore::Semaphore;
let sem = Semaphore::new(2);
// First acquisition succeeds
let permit1 = sem.try_acquire(1).unwrap();
assert_eq!(sem.available_permits(), 1);
// Second acquisition succeeds
let permit2 = sem.try_acquire(1).unwrap();
assert_eq!(sem.available_permits(), 0);
// Third acquisition fails
assert!(sem.try_acquire(1).is_none());Sourcepub async fn acquire(&self, permits: usize) -> SemaphorePermit<'_>
pub async fn acquire(&self, permits: usize) -> SemaphorePermit<'_>
Acquires n permits from the semaphore.
If the permits are not immediately available, this method will wait until they become
available. Returns a SemaphorePermit that will release the permits when dropped.
§Cancel safety
Pending acquisitions complete in order. Cancelling this call loses its place among them.
§Examples
use std::sync::Arc;
use asyncband::semaphore::Semaphore;
let sem = Arc::new(Semaphore::new(2));
let sem2 = sem.clone();
let handle = tokio::spawn(async move {
let permit = sem2.acquire(1).await;
// Do some work with the permit.
// Permit is automatically released when dropped.
});
let permit = sem.acquire(1).await;
// Do some work with the permit
drop(permit); // Explicitly release the permit
handle.await.unwrap();Sourcepub fn try_acquire_owned(
self: Arc<Self>,
permits: usize,
) -> Option<OwnedSemaphorePermit>
pub fn try_acquire_owned( self: Arc<Self>, permits: usize, ) -> Option<OwnedSemaphorePermit>
Attempts to acquire n permits from the semaphore without blocking.
The semaphore must be wrapped in an Arc to call this method.
If the permits are successfully acquired, a OwnedSemaphorePermit is returned.
The permits will be automatically returned to the semaphore when the permit
is dropped, unless forget is called.
§Examples
use std::sync::Arc;
use asyncband::semaphore::Semaphore;
let sem = Arc::new(Semaphore::new(2));
let p1 = sem.clone().try_acquire_owned(1).unwrap();
assert_eq!(sem.available_permits(), 1);
let p2 = sem.clone().try_acquire_owned(1).unwrap();
assert_eq!(sem.available_permits(), 0);
let p3 = sem.try_acquire_owned(1);
assert!(p3.is_none());Sourcepub async fn acquire_owned(
self: Arc<Self>,
permits: usize,
) -> OwnedSemaphorePermit
pub async fn acquire_owned( self: Arc<Self>, permits: usize, ) -> OwnedSemaphorePermit
Acquires n permits from the semaphore.
The semaphore must be wrapped in an Arc to call this method.
If the permits are not immediately available, this method will wait until they become
available. Returns a OwnedSemaphorePermit that will release the permits when dropped.
§Cancel safety
Pending acquisitions complete in order. Cancelling this call loses its place among them.
§Examples
use std::sync::Arc;
use asyncband::semaphore::Semaphore;
let sem = Arc::new(Semaphore::new(3));
let mut join_handles = vec![];
for _ in 0..5 {
let permit = sem.clone().acquire_owned(1).await;
join_handles.push(tokio::spawn(async move {
// perform task...
// explicitly own `permit` in the task
drop(permit);
}));
}
for handle in join_handles {
handle.await.unwrap();
}