Skip to main content

Semaphore

Struct Semaphore 

Source
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

Source

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 permits
Source

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);
Source

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);
Source

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);
Source

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);
Source

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());
Source

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();
Source

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());
Source

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();
}

Trait Implementations§

Source§

impl Debug for Semaphore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.