Struct holochain::prelude::dependencies::kitsune_p2p_types::dependencies::lair_keystore_api::dependencies::tokio::sync::Semaphore
source · 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§
source§impl Semaphore
impl Semaphore
sourcepub const MAX_PERMITS: usize = 2_305_843_009_213_693_951usize
pub const MAX_PERMITS: usize = 2_305_843_009_213_693_951usize
The maximum number of permits which a semaphore can hold. It is usize::MAX >>> 3
.
Exceeding this limit typically results in a panic.
sourcepub fn new(permits: usize) -> Semaphore
pub fn new(permits: usize) -> Semaphore
Creates a new semaphore with the initial number of permits.
Panics if permits
exceeds Semaphore::MAX_PERMITS
.
sourcepub const fn const_new(permits: usize) -> Semaphore
pub const fn const_new(permits: usize) -> Semaphore
Creates a new semaphore with the initial number of permits.
Examples
use tokio::sync::Semaphore;
static SEM: Semaphore = Semaphore::const_new(10);
sourcepub fn available_permits(&self) -> usize
pub fn available_permits(&self) -> usize
Returns the current number of available permits.
sourcepub fn add_permits(&self, n: usize)
pub fn add_permits(&self, n: usize)
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.
sourcepub async fn acquire(
&self
) -> impl Future<Output = Result<SemaphorePermit<'_>, AcquireError>>
pub async fn acquire(
&self
) -> impl Future<Output = Result<SemaphorePermit<'_>, AcquireError>>
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);
}
sourcepub async fn acquire_many(
&self,
n: u32
) -> impl Future<Output = Result<SemaphorePermit<'_>, AcquireError>>
pub async fn acquire_many(
&self,
n: u32
) -> impl Future<Output = Result<SemaphorePermit<'_>, AcquireError>>
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);
}
sourcepub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>
pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>
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));
sourcepub fn try_acquire_many(
&self,
n: u32
) -> Result<SemaphorePermit<'_>, TryAcquireError>
pub fn try_acquire_many(
&self,
n: u32
) -> Result<SemaphorePermit<'_>, TryAcquireError>
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));
sourcepub async fn acquire_owned(
self: Arc<Semaphore>
) -> impl Future<Output = Result<OwnedSemaphorePermit, AcquireError>>
pub async fn acquire_owned(
self: Arc<Semaphore>
) -> impl Future<Output = Result<OwnedSemaphorePermit, AcquireError>>
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();
}
}
sourcepub async fn acquire_many_owned(
self: Arc<Semaphore>,
n: u32
) -> impl Future<Output = Result<OwnedSemaphorePermit, AcquireError>>
pub async fn acquire_many_owned(
self: Arc<Semaphore>,
n: u32
) -> impl Future<Output = Result<OwnedSemaphorePermit, AcquireError>>
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();
}
}
sourcepub fn try_acquire_owned(
self: Arc<Semaphore>
) -> Result<OwnedSemaphorePermit, TryAcquireError>
pub fn try_acquire_owned(
self: Arc<Semaphore>
) -> Result<OwnedSemaphorePermit, TryAcquireError>
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));
sourcepub fn try_acquire_many_owned(
self: Arc<Semaphore>,
n: u32
) -> Result<OwnedSemaphorePermit, TryAcquireError>
pub fn try_acquire_many_owned(
self: Arc<Semaphore>,
n: u32
) -> Result<OwnedSemaphorePermit, TryAcquireError>
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));
sourcepub fn close(&self)
pub fn close(&self)
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))
}
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for Semaphore
impl Send for Semaphore
impl Sync for Semaphore
impl Unpin for Semaphore
impl !UnwindSafe for Semaphore
Blanket Implementations§
§impl<T> Any for Twhere
T: Any + ?Sized,
impl<T> Any for Twhere
T: Any + ?Sized,
§fn type_id_compat(&self) -> TypeId
fn type_id_compat(&self) -> TypeId
§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
§type ArchivedMetadata = ()
type ArchivedMetadata = ()
§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata
) -> <T as Pointee>::Metadata
§impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
impl<F, W, T, D> Deserialize<With<T, W>, D> for Fwhere
W: DeserializeWith<F, T, D>,
D: Fallible + ?Sized,
F: ?Sized,
§fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
fn deserialize(
&self,
deserializer: &mut D
) -> Result<With<T, W>, <D as Fallible>::Error>
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
§impl<T> Pointable for T
impl<T> Pointable for T
§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.