pub struct OnceCell<T> { /* private fields */ }Expand description
A thread-safe cell whose value is asynchronously initialized at most once.
Callers provide an initializer when accessing an empty cell. An initializer that returns an
error, panics, or is cancelled leaves the cell empty so a later caller can retry. Use
LazyCell instead when the cell should own a one-shot initializer and preserve its in-flight
future across caller cancellation.
§Examples
use std::sync::Arc;
use asyncband::once::OnceCell;
static CELL: OnceCell<u8> = OnceCell::new();
let handle1 = tokio::spawn(async { CELL.get_or_init(move || async { 1 }).await });
let handle2 = tokio::spawn(async { CELL.get_or_init(move || async { 2 }).await });
let result1 = handle1.await.unwrap();
let result2 = handle2.await.unwrap();
assert_eq!(result1, result2);
assert!(*result1 == 1 || *result1 == 2);Implementations§
Source§impl<T> OnceCell<T>
impl<T> OnceCell<T>
Sourcepub const fn from_value(value: T) -> Self
pub const fn from_value(value: T) -> Self
Creates a new OnceCell initialized with the provided value.
Sourcepub fn get(&self) -> Option<&T>
pub fn get(&self) -> Option<&T>
Returns the stored value.
Returns None if the cell is uninitialized, or being initialized.
This method never blocks.
Sourcepub fn get_mut(&mut self) -> Option<&mut T>
pub fn get_mut(&mut self) -> Option<&mut T>
Returns mutable access to the stored value.
Returns None if the cell is uninitialized.
This method never blocks. Since it borrows the OnceCell mutably, it is statically
guaranteed that no active borrows to the OnceCell exist, including from other threads.
Sourcepub async fn get_or_init<F>(&self, init: F) -> &Twhere
F: AsyncFnOnce() -> T,
pub async fn get_or_init<F>(&self, init: F) -> &Twhere
F: AsyncFnOnce() -> T,
Returns the value, initializing an empty cell with the provided asynchronous function.
If some other task is currently working on initializing the OnceCell, this call will wait
for that other task to finish, then return the value that the other task produced.
If the provided operation is cancelled, the initialization attempt is cancelled. If there are other tasks waiting for the value to be initialized, one of them will start another attempt at initializing the value.
This will deadlock if init tries to initialize the cell recursively.
Sourcepub async fn get_or_try_init<E, F>(&self, init: F) -> Result<&T, E>where
F: AsyncFnOnce() -> Result<T, E>,
pub async fn get_or_try_init<E, F>(&self, init: F) -> Result<&T, E>where
F: AsyncFnOnce() -> Result<T, E>,
Returns the value, initializing an empty cell with the provided fallible asynchronous function.
If some other task is currently working on initializing the OnceCell, this call will wait
for that other task to finish, then return the value that the other task produced.
If the provided operation returns an error, is cancelled or panics, the initialization attempt is cancelled. If there are other tasks waiting for the value to be initialized one of them will start another attempt at initializing the value.
This will deadlock if init tries to initialize the cell recursively.
Sourcepub async fn get_mut_or_init<F>(&mut self, init: F) -> &mut Twhere
F: AsyncFnOnce() -> T,
pub async fn get_mut_or_init<F>(&mut self, init: F) -> &mut Twhere
F: AsyncFnOnce() -> T,
Returns mutable access to the value, initializing an empty cell asynchronously.
This method never blocks other tasks because it takes &mut self, which guarantees
exclusive access to the OnceCell and thus no concurrent initialization can be in
progress.
If the cell is already initialized, it returns a mutable reference to the existing value.
Otherwise, it runs init, stores the result, and returns a mutable reference to the newly
initialized value.
§Examples
use asyncband::once::OnceCell;
let mut cell: OnceCell<u32> = OnceCell::new();
let v = cell.get_mut_or_init(|| async { 41 }).await;
*v += 1;
assert_eq!(*cell.get().unwrap(), 42);Sourcepub async fn get_mut_or_try_init<E, F>(&mut self, init: F) -> Result<&mut T, E>where
F: AsyncFnOnce() -> Result<T, E>,
pub async fn get_mut_or_try_init<E, F>(&mut self, init: F) -> Result<&mut T, E>where
F: AsyncFnOnce() -> Result<T, E>,
Returns mutable access to the value, initializing an empty cell with a fallible asynchronous function.
This method never blocks other tasks because it takes &mut self, which guarantees
exclusive access to the OnceCell and thus no concurrent initialization can be in
progress.
If the cell is already initialized, it returns a mutable reference to the existing value.
Otherwise, it runs init. On success, it stores the result and returns a mutable
reference to the newly initialized value. On error, it returns the error and leaves the
cell uninitialized.
§Examples
use asyncband::once::OnceCell;
let mut cell: OnceCell<u32> = OnceCell::new();
assert!(
cell.get_mut_or_try_init(|| async { Err(()) })
.await
.is_err()
);
let v = cell
.get_mut_or_try_init(|| async { Ok::<_, ()>(10) })
.await
.unwrap();
*v += 5;
assert_eq!(*cell.get().unwrap(), 15);Sourcepub async fn try_insert(&self, value: T) -> Result<&T, (&T, T)>
pub async fn try_insert(&self, value: T) -> Result<&T, (&T, T)>
Initializes the contents of the cell to value if the cell was uninitialized,
then returns a reference to it.
May wait if another task is currently attempting to initialize the cell. The cell is
guaranteed to contain a value when try_insert returns, though not necessarily the
one provided.
Returns Ok(&value) if the cell was uninitialized and Err((¤t_value, value))
if it was already initialized.
§Examples
use asyncband::once::OnceCell;
static CELL: OnceCell<i32> = OnceCell::new();
assert!(CELL.get().is_none());
tokio::spawn(async {
assert_eq!(CELL.try_insert(92).await, Ok(&92));
})
.await
.unwrap();
assert_eq!(CELL.try_insert(62).await, Err((&92, 62)));
assert_eq!(CELL.get(), Some(&92));Sourcepub async fn set(&self, value: T) -> Result<(), T>
pub async fn set(&self, value: T) -> Result<(), T>
Initializes the contents of the cell to value.
May wait if another thread is currently attempting to initialize the cell. The cell is
guaranteed to contain a value when set returns, though not necessarily the one provided.
Returns Ok(()) if the cell was uninitialized and Err(value) if the cell was already
initialized.
§Examples
use asyncband::once::OnceCell;
static CELL: OnceCell<i32> = OnceCell::new();
assert!(CELL.get().is_none());
tokio::spawn(async {
assert_eq!(CELL.set(92).await, Ok(()));
})
.await
.unwrap();
assert_eq!(CELL.set(62).await, Err(62));
assert_eq!(CELL.get(), Some(&92));Sourcepub fn into_inner(self) -> Option<T>
pub fn into_inner(self) -> Option<T>
Consumes the OnceCell, returning the wrapped value. Returns None if the cell was
uninitialized.
§Examples
use asyncband::once::OnceCell;
let cell: OnceCell<String> = OnceCell::new();
assert_eq!(cell.into_inner(), None);
let cell = OnceCell::new();
cell.set("hello".to_string()).await.unwrap();
assert_eq!(cell.into_inner(), Some("hello".to_string()));Sourcepub fn take(&mut self) -> Option<T>
pub fn take(&mut self) -> Option<T>
Takes the value out of this OnceCell, moving it back to an uninitialized state.
Has no effect and returns None if the OnceCell was uninitialized.
Since this method borrows the OnceCell mutably, it is statically guaranteed that
no active borrows to the OnceCell exist, including from other threads.
§Examples
use asyncband::once::OnceCell;
let mut cell: OnceCell<String> = OnceCell::new();
assert_eq!(cell.take(), None);
let mut cell = OnceCell::new();
cell.set("hello".to_string()).await.unwrap();
assert_eq!(cell.take(), Some("hello".to_string()));
assert_eq!(cell.get(), None);