Skip to main content

Semaphore

Struct Semaphore 

Source
pub struct Semaphore<P: Priority, Q: SemaphoreQueue<P> = DefaultSemaphoreQueue<P>>(/* private fields */);
Expand description

An async semaphore where queued waiters are granted permits by order of priority.

With the evict flag enabled, existing handles will be requested to return their permits back to the queue (which may be echecked / waited for via evicted)

Note that to minimize waiting, requesters with the same priority will additionally be sorted by permit count (lowest first). If this isn’t desireable, use a Priority wraper like FIFO or LIFO. This makes it so requesters won’t be blocked by larger requests with the same priority.

The default queue used may change, however its characteristics will remain the same, notably:

Implementations§

Source§

impl<P: Priority, Q: SemaphoreQueue<P>> Semaphore<P, Q>

Source

pub fn new(capacity: usize) -> Self

Create a new semaphore with permits permits available.

Source

pub const fn const_new(permits: usize) -> Self
where Q: ConstDefault,

Create a new semaphore with permits permits available. Usable for const if the underlying queue is ConstDefault and the const-default feature is enabled.

All builtin queues impl ConstDefault.

Source

pub fn acquire( &self, priority: P, ) -> impl Future<Output = SemaphorePermit<'_, P, Q>>

Acquire a single permit, waiting if necessary. Permits will be issued by order of priority.

Source

pub fn acquire_from( &self, priority: impl Into<P>, ) -> impl Future<Output = SemaphorePermit<'_, P, Q>>

Acquire a single permit, waiting if necessary.

Shorthand for acquire(priority.into()).

Cancel Safety: This function is cancel safe.

Source

pub fn acquire_default(&self) -> impl Future<Output = SemaphorePermit<'_, P, Q>>
where P: Default,

Acquire a permit with the Default priority.

Shorthand for acquire with Default::default().

Cancel Safety: This function is cancel safe.

Source

pub async fn acquire_many( &self, priority: P, count: usize, ) -> SemaphorePermit<'_, P, Q>

Acquire multiple permits, waiting if necessary. Permits will be issued by order of priority. Lower priority waiters will be blocked until all requested permits are acquired (and subsequently released).

Panics if count >= MAX_PERMITS (usize::MAX >> 1).

Cancel Safety: This function is cancel safe.

Source

pub async fn acquire_many_default( &self, count: usize, ) -> impl Future<Output = SemaphorePermit<'_, P, Q>>
where P: Default,

Acquire multiple permits with the Default priority.

Panics if count >= MAX_PERMITS (usize::MAX >> 1).

Shorthand for acquire_many with Default::default().

Cancel Safety: This function is cancel safe.

Source

pub async fn acquire_many_from( &self, count: usize, priority: impl Into<P>, ) -> impl Future<Output = SemaphorePermit<'_, P, Q>>
where P: Default,

Acquire multiple permits with the .

Panics if count >= MAX_PERMITS (usize::MAX >> 1).

Shorthand for acquire_many with priority.into().

Cancel Safety: This function is cancel safe.

Source

pub async fn acquire_within_total( &self, priority: P, count: usize, ) -> Result<SemaphorePermit<'_, P, Q>, InsufficientPermitsError>

Acquire count permits without blocking the queue if the requested count of permits is more than the total associated. If the semaphore lacks sufficient associated permits or loses them while waiting, this returns an InsufficientPermitsError.

Example:

let sem = Semaphore::<usize>::new(10);

let permit = sem.acquire(0).await;
// try to acquire 10 permits
let mut many_permits_fut = pin!(sem.acquire_within_total(1, 10));
tokio::select! {
    _ = tokio::time::sleep(Duration::from_secs(1)) => {},
    // can't happen
    _ =  many_permits_fut.as_mut() => { panic!("total of 11 tokens held")},
};

// remove 1 permit from the semaphore
permit.forget();

assert!(many_permits_fut.await.is_err());

Cancel Safety: This function is cancel safe.

Source

pub fn add_permits(&self, count: usize) -> usize

Add permits to the semaphore.

Panics if:

  • The count of permits to add would overflow available
  • (if the semaphore-total feature is enabled) The count of permits plus the current total would overflow.

Use try_add_permits if overflows may occur.

Note that if the semaphore-total feature isn’t enabled, the sum of permits issued + permits available can exceed the max usize and overflow. If an owned permit is dropped and would cause an overflow when adding held permits back to available, it will panic. The semaphore itself will remain usable, however the permits will be discarded.

For compatibility, it’s best to assume that it’s unsafe to exceed usize::MAX permits associated with a semaphore, even if the semaphore-total flag isn’t enabled (as other crates may require it) (associated permi.ts being available + sum of permits issued)

Source

pub fn total_permits(&self) -> usize

Returns the capacity / total count of permits associated with the semaphore..

Source

pub fn available_permits(&self) -> usize

Returns the amount of currently available permits.

Source

pub fn try_add_permits(&self, count: usize) -> Result<usize, ()>

Try adding permits, returning an error if adding the permits would overflow. See the notes on add_permits for more details.

Source

pub fn forget_permits(&self, count: usize) -> usize

Forget up to count permits, up to the currently available amount. Returns the amount of permits forgotten.

If n permits need to be removed, calling acquire_many with the highest priority then calling forget on the returned guard may be a better choice.

(if the semaphore-total flag is enabled, acquire_within_total may be a safer choice than acquire_many - if it’s possible for any permits to be forgotten elsewhere)

Trait Implementations§

Source§

impl<P: Priority, Q: ConstDefault + SemaphoreQueue<P>> ConstDefault for Semaphore<P, Q>

Available on crate feature const-default only.
Source§

const DEFAULT: Self

The constant default value.
Source§

impl<P: Priority, Q: SemaphoreQueue<P>> Debug for Semaphore<P, Q>

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<P: Default + Priority, Q: Default + SemaphoreQueue<P>> Default for Semaphore<P, Q>

Source§

fn default() -> Semaphore<P, Q>

Returns the “default value” for a type. Read more
Source§

impl<P: Priority, Q: SemaphoreQueue<P> + Send> Send for Semaphore<P, Q>

Source§

impl<P: Priority, Q: SemaphoreQueue<P> + Send + Sync> Sync for Semaphore<P, Q>

Auto Trait Implementations§

§

impl<P, Q = ArenaQueue<DualLinkArenaQueueNode<SemaphoreWaiter<P>>>> !Freeze for Semaphore<P, Q>

§

impl<P, Q> RefUnwindSafe for Semaphore<P, Q>

§

impl<P, Q> Unpin for Semaphore<P, Q>
where Q: Unpin, P: Unpin,

§

impl<P, Q> UnsafeUnpin for Semaphore<P, Q>
where Q: UnsafeUnpin,

§

impl<P, Q> UnwindSafe for Semaphore<P, Q>

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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.