pub struct Semaphore { /* private fields */ }
Expand description

Counting semaphore performing asynchronous permit acquisition.

A semaphore maintains a set of permits. Permits are used to synchronize access to a shared resource. A semaphore differs from a mutex in that it can allow more than one concurrent caller to access the shared resource at a time.

When acquire is called and the semaphore has remaining permits, the function immediately returns a permit. However, if no remaining permits are available, acquire (asynchronously) waits until an outstanding permit is dropped. At this point, the freed permit is assigned to the caller.

This Semaphore is fair, which means that permits are given out in the order they were requested. This fairness is also applied when acquire_many gets involved, so if a call to acquire_many at the front of the queue requests more permits than currently available, this can prevent a call to acquire from completing, even if the semaphore has enough permits complete the call to acquire.

To use the Semaphore in a poll function, you can use the PollSemaphore utility.

Examples

Basic usage:

use tokio::sync::{Semaphore, TryAcquireError};

#[tokio::main]
async fn main() {
    let semaphore = Semaphore::new(3);

    let a_permit = semaphore.acquire().await.unwrap();
    let two_permits = semaphore.acquire_many(2).await.unwrap();

    assert_eq!(semaphore.available_permits(), 0);

    let permit_attempt = semaphore.try_acquire();
    assert_eq!(permit_attempt.err(), Some(TryAcquireError::NoPermits));
}

Use Semaphore::acquire_owned to move permits across tasks:

use std::sync::Arc;
use tokio::sync::Semaphore;

#[tokio::main]
async fn main() {
    let semaphore = Arc::new(Semaphore::new(3));
    let mut join_handles = Vec::new();

    for _ in 0..5 {
        let permit = semaphore.clone().acquire_owned().await.unwrap();
        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();
    }
}

Implementations§

The maximum number of permits which a semaphore can hold. It is usize::MAX >>> 3.

Exceeding this limit typically results in a panic.

Creates a new semaphore with the initial number of permits.

Panics if permits exceeds Semaphore::MAX_PERMITS.

Creates a new semaphore with the initial number of permits.

Examples
use tokio::sync::Semaphore;

static SEM: Semaphore = Semaphore::const_new(10);

Returns the current number of available permits.

Adds n new permits to the semaphore.

The maximum number of permits is Semaphore::MAX_PERMITS, and this function will panic if the limit is exceeded.

Acquires a permit from the semaphore.

If the semaphore has been closed, this returns an AcquireError. Otherwise, this returns a SemaphorePermit representing the acquired permit.

Cancel safety

This method uses a queue to fairly distribute permits in the order they were requested. Cancelling a call to acquire makes you lose your place in the queue.

Examples
use tokio::sync::Semaphore;

#[tokio::main]
async fn main() {
    let semaphore = Semaphore::new(2);

    let permit_1 = semaphore.acquire().await.unwrap();
    assert_eq!(semaphore.available_permits(), 1);

    let permit_2 = semaphore.acquire().await.unwrap();
    assert_eq!(semaphore.available_permits(), 0);

    drop(permit_1);
    assert_eq!(semaphore.available_permits(), 1);
}

Acquires n permits from the semaphore.

If the semaphore has been closed, this returns an AcquireError. Otherwise, this returns a SemaphorePermit representing the acquired permits.

Cancel safety

This method uses a queue to fairly distribute permits in the order they were requested. Cancelling a call to acquire_many makes you lose your place in the queue.

Examples
use tokio::sync::Semaphore;

#[tokio::main]
async fn main() {
    let semaphore = Semaphore::new(5);

    let permit = semaphore.acquire_many(3).await.unwrap();
    assert_eq!(semaphore.available_permits(), 2);
}

Tries to acquire a permit from the semaphore.

If the semaphore has been closed, this returns a TryAcquireError::Closed and a TryAcquireError::NoPermits if there are no permits left. Otherwise, this returns a SemaphorePermit representing the acquired permits.

Examples
use tokio::sync::{Semaphore, TryAcquireError};

let semaphore = Semaphore::new(2);

let permit_1 = semaphore.try_acquire().unwrap();
assert_eq!(semaphore.available_permits(), 1);

let permit_2 = semaphore.try_acquire().unwrap();
assert_eq!(semaphore.available_permits(), 0);

let permit_3 = semaphore.try_acquire();
assert_eq!(permit_3.err(), Some(TryAcquireError::NoPermits));

Tries to acquire n permits from the semaphore.

If the semaphore has been closed, this returns a TryAcquireError::Closed and a TryAcquireError::NoPermits if there are not enough permits left. Otherwise, this returns a SemaphorePermit representing the acquired permits.

Examples
use tokio::sync::{Semaphore, TryAcquireError};

let semaphore = Semaphore::new(4);

let permit_1 = semaphore.try_acquire_many(3).unwrap();
assert_eq!(semaphore.available_permits(), 1);

let permit_2 = semaphore.try_acquire_many(2);
assert_eq!(permit_2.err(), Some(TryAcquireError::NoPermits));

Acquires a permit from the semaphore.

The semaphore must be wrapped in an Arc to call this method. If the semaphore has been closed, this returns an AcquireError. Otherwise, this returns a OwnedSemaphorePermit representing the acquired permit.

Cancel safety

This method uses a queue to fairly distribute permits in the order they were requested. Cancelling a call to acquire_owned makes you lose your place in the queue.

Examples
use std::sync::Arc;
use tokio::sync::Semaphore;

#[tokio::main]
async fn main() {
    let semaphore = Arc::new(Semaphore::new(3));
    let mut join_handles = Vec::new();

    for _ in 0..5 {
        let permit = semaphore.clone().acquire_owned().await.unwrap();
        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();
    }
}

Acquires n permits from the semaphore.

The semaphore must be wrapped in an Arc to call this method. If the semaphore has been closed, this returns an AcquireError. Otherwise, this returns a OwnedSemaphorePermit representing the acquired permit.

Cancel safety

This method uses a queue to fairly distribute permits in the order they were requested. Cancelling a call to acquire_many_owned makes you lose your place in the queue.

Examples
use std::sync::Arc;
use tokio::sync::Semaphore;

#[tokio::main]
async fn main() {
    let semaphore = Arc::new(Semaphore::new(10));
    let mut join_handles = Vec::new();

    for _ in 0..5 {
        let permit = semaphore.clone().acquire_many_owned(2).await.unwrap();
        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();
    }
}

Tries to acquire a permit from the semaphore.

The semaphore must be wrapped in an Arc to call this method. If the semaphore has been closed, this returns a TryAcquireError::Closed and a TryAcquireError::NoPermits if there are no permits left. Otherwise, this returns a OwnedSemaphorePermit representing the acquired permit.

Examples
use std::sync::Arc;
use tokio::sync::{Semaphore, TryAcquireError};

let semaphore = Arc::new(Semaphore::new(2));

let permit_1 = Arc::clone(&semaphore).try_acquire_owned().unwrap();
assert_eq!(semaphore.available_permits(), 1);

let permit_2 = Arc::clone(&semaphore).try_acquire_owned().unwrap();
assert_eq!(semaphore.available_permits(), 0);

let permit_3 = semaphore.try_acquire_owned();
assert_eq!(permit_3.err(), Some(TryAcquireError::NoPermits));

Tries to acquire n permits from the semaphore.

The semaphore must be wrapped in an Arc to call this method. If the semaphore has been closed, this returns a TryAcquireError::Closed and a TryAcquireError::NoPermits if there are no permits left. Otherwise, this returns a OwnedSemaphorePermit representing the acquired permit.

Examples
use std::sync::Arc;
use tokio::sync::{Semaphore, TryAcquireError};

let semaphore = Arc::new(Semaphore::new(4));

let permit_1 = Arc::clone(&semaphore).try_acquire_many_owned(3).unwrap();
assert_eq!(semaphore.available_permits(), 1);

let permit_2 = semaphore.try_acquire_many_owned(2);
assert_eq!(permit_2.err(), Some(TryAcquireError::NoPermits));

Closes the semaphore.

This prevents the semaphore from issuing new permits and notifies all pending waiters.

Examples
use tokio::sync::Semaphore;
use std::sync::Arc;
use tokio::sync::TryAcquireError;

#[tokio::main]
async fn main() {
    let semaphore = Arc::new(Semaphore::new(1));
    let semaphore2 = semaphore.clone();

    tokio::spawn(async move {
        let permit = semaphore.acquire_many(2).await;
        assert!(permit.is_err());
        println!("waiter received error");
    });

    println!("closing semaphore");
    semaphore2.close();

    // Cannot obtain more permits
    assert_eq!(semaphore2.try_acquire().err(), Some(TryAcquireError::Closed))
}

Returns true if the semaphore is closed

Trait Implementations§

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
TODO: once 1.33.0 is the minimum supported compiler version, remove Any::type_id_compat and use StdAny::type_id instead. https://github.com/rust-lang/rust/issues/27745
The archived version of the pointer metadata for this type.
Converts some archived metadata to the pointer metadata for itself.
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Deserializes using the given deserializer

Returns the argument unchanged.

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Attaches the current Context to this type, returning a WithContext wrapper. Read more
Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Instruments this type with the current Span, returning an Instrumented wrapper. Read more

Calls U::from(self).

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

The alignment of pointer.
The type for initializers.
Initializes a with the given initializer. Read more
Dereferences the given pointer. Read more
Mutably dereferences the given pointer. Read more
Drops the object pointed to by the given pointer. Read more
The type for metadata in pointers and references to Self.
Should always be Self
The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Checks if self is actually part of its subset T (and can be converted to it).
Use with care! Same as self.to_subset but without any property checks. Always succeeds.
The inclusion map: converts self to the equivalent element of its superset.
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.
upcast ref
upcast mut ref
upcast boxed dyn
Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more