pub struct Once { /* private fields */ }Expand description
A synchronization primitive which can be used to run a one-time async initialization.
Unlike std::sync::Once, this type never blocks a thread. The provided closure must
produce a future and the future is awaited inside the primitive. Coordination happens
with asynchronous Semaphore, which keeps the implementation runtime-agnostic.
This type also intentionally omits “poisoning” semantics. If an initialization future is
cancelled or panics, the attempt is abandoned and other tasks may retry the operation.
Encode partial-initialization detection in the future itself (e.g. return a Result)
when needed.
See the module level documentation for additional context.
§Examples
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use asyncband::once::Once;
static ONCE: Once = Once::new();
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let handle1 = tokio::spawn(async {
ONCE.call_once(async || {
COUNTER.fetch_add(1, Ordering::SeqCst);
})
.await;
});
let handle2 = tokio::spawn(async {
ONCE.call_once(async || {
COUNTER.fetch_add(1, Ordering::SeqCst);
})
.await;
});
handle1.await.unwrap();
handle2.await.unwrap();
// The counter is incremented only once, even though two tasks called `call_once`.
assert_eq!(COUNTER.load(Ordering::SeqCst), 1);Implementations§
Source§impl Once
impl Once
Sourcepub fn is_completed(&self) -> bool
pub fn is_completed(&self) -> bool
Returns true if some call_once has completed successfully.
§Examples
use asyncband::once::Once;
static ONCE: Once = Once::new();
assert!(!ONCE.is_completed());
ONCE.call_once(async || {}).await;
assert!(ONCE.is_completed());Sourcepub async fn call_once<F>(&self, f: F)where
F: AsyncFnOnce(),
pub async fn call_once<F>(&self, f: F)where
F: AsyncFnOnce(),
Calls the given async closure if this is the first time call_once has been called
on this Once instance.
If another task is currently running the closure, this call will wait for that task to complete.
If the provided operation is cancelled, the initialization attempt is cancelled. If there are other tasks waiting, one of them will start another attempt.
Calling call_once recursively on the same Once from within the closure will deadlock, because the closure holds the semaphore permit while trying to acquire it again.
§Examples
use asyncband::once::Once;
static ONCE: Once = Once::new();
ONCE.call_once(async || {
println!("Do some one-time async thing.");
})
.await;Sourcepub async fn wait(&self)
pub async fn wait(&self)
Waits asynchronously until some call_once has completed successfully.
§Examples
use asyncband::once::Once;
static ONCE: Once = Once::new();
let handle = tokio::spawn(async {
ONCE.wait().await;
});
ONCE.call_once(async || {
println!("initialized");
})
.await;
handle.await.unwrap();