Skip to main content

OnceCell

Struct OnceCell 

Source
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>

Source

pub const fn new() -> Self

Creates a new empty OnceCell.

Source

pub const fn from_value(value: T) -> Self

Creates a new OnceCell initialized with the provided value.

Source

pub fn get(&self) -> Option<&T>

Returns the stored value.

Returns None if the cell is uninitialized, or being initialized.

This method never blocks.

Source

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.

Source

pub async fn get_or_init<F>(&self, init: F) -> &T
where 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.

Source

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.

Source

pub async fn get_mut_or_init<F>(&mut self, init: F) -> &mut T
where 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);
Source

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);
Source

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((&current_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));
Source

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));
Source

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()));
Source

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);

Trait Implementations§

Source§

impl<T: Clone> Clone for OnceCell<T>

Source§

fn clone(&self) -> OnceCell<T>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for OnceCell<T>

Source§

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

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

impl<T> Default for OnceCell<T>

Source§

fn default() -> Self

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

impl<T: Eq> Eq for OnceCell<T>

Source§

impl<T> From<T> for OnceCell<T>

Source§

fn from(value: T) -> Self

Converts to this type from the input type.
Source§

impl<T: PartialEq> PartialEq for OnceCell<T>

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for OnceCell<T>

§

impl<T> !RefUnwindSafe for OnceCell<T>

§

impl<T> Send for OnceCell<T>
where ValueCell<T>: Send,

§

impl<T> Sync for OnceCell<T>
where ValueCell<T>: Sync,

§

impl<T> Unpin for OnceCell<T>
where ValueCell<T>: Unpin,

§

impl<T> UnsafeUnpin for OnceCell<T>
where ValueCell<T>: UnsafeUnpin,

§

impl<T> UnwindSafe for OnceCell<T>
where ValueCell<T>: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.