Struct OnceLock
struct OnceLock<T> { ... }
A synchronization primitive which can nominally be written to only once.
This type is a thread-safe OnceCell, and can be used in statics.
In many simple cases, you can use LazyLock<T, F> instead to get the benefits of this type
with less effort: LazyLock<T, F> "looks like" &T because it initializes with F on deref!
Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
doesn't allow additional inputs to its function after you call LazyLock::new(|| ...).
A OnceLock can be thought of as a safe abstraction over uninitialized data that becomes
initialized once written.
Unlike Mutex, OnceLock is never poisoned on panic.
Examples
Writing to a OnceLock from a separate thread:
use OnceLock;
static CELL: = new;
// `OnceLock` has not been written to yet.
assert!;
// Spawn a thread and write to `OnceLock`.
spawn
.join
.unwrap;
// `OnceLock` now contains the value.
assert_eq!;
You can use OnceLock to implement a type that requires "append-only" logic:
use ;
use thread;
// Let's exercise this new Sync append-only list by doing a little counting
static LIST: = new;
static COUNTER: AtomicU32 = new;
# const LEN: u32 = if cfg! else ;
# /*
const LEN: u32 = 1000;
# */
scope;
for i in 0..LEN
Implementations
impl<T> OnceLock<T>
const fn new() -> OnceLock<T>Creates a new uninitialized cell.
fn get(self: &Self) -> Option<&T>Gets the reference to the underlying value.
Returns
Noneif the cell is uninitialized, or being initialized. This method never blocks.fn get_mut(self: &mut Self) -> Option<&mut T>Gets the mutable reference to the underlying value.
Returns
Noneif the cell is uninitialized.This method never blocks. Since it borrows the
OnceLockmutably, it is statically guaranteed that no active borrows to theOnceLockexist, including from other threads.fn wait(self: &Self) -> &TBlocks the current thread until the cell is initialized.
Example
Waiting for a computation on another thread to finish:
use thread; use OnceLock; let value = new; scopefn set(self: &Self, value: T) -> Result<(), T>Initializes the contents of the cell to
value.May block if another thread is currently attempting to initialize the cell. The cell is guaranteed to contain a value when
setreturns, though not necessarily the one provided.Returns
Ok(())if the cell was uninitialized andErr(value)if the cell was already initialized.Examples
use OnceLock; static CELL: = new;fn try_insert(self: &Self, value: T) -> Result<&T, (&T, T)>Initializes the contents of the cell to
valueif the cell was uninitialized, then returns a reference to it.May block if another thread is currently attempting to initialize the cell. The cell is guaranteed to contain a value when
try_insertreturns, though not necessarily the one provided.Returns
Ok(&value)if the cell was uninitialized andErr((¤t_value, value))if it was already initialized.Examples
use OnceLock; static CELL: = new;fn get_or_init<F>(self: &Self, f: F) -> &T where F: FnOnce() -> TGets the contents of the cell, initializing it to
f()if the cell was uninitialized.Many threads may call
get_or_initconcurrently with different initializing functions, but it is guaranteed that only one function will be executed if the function doesn't panic.Panics
If
f()panics, the panic is propagated to the caller, and the cell remains uninitialized.It is an error to reentrantly initialize the cell from
f. The exact outcome is unspecified. Current implementation deadlocks, but this may be changed to a panic in the future.Examples
use OnceLock; let cell = new; let value = cell.get_or_init; assert_eq!; let value = cell.get_or_init; assert_eq!;fn get_mut_or_init<F>(self: &mut Self, f: F) -> &mut T where F: FnOnce() -> TGets the mutable reference of the contents of the cell, initializing it to
f()if the cell was uninitialized.This method never blocks. Since it borrows the
OnceLockmutably, it is statically guaranteed that no active borrows to theOnceLockexist, including from other threads.Panics
If
f()panics, the panic is propagated to the caller, and the cell remains uninitialized.Examples
use OnceLock; let mut cell = new; let value = cell.get_mut_or_init; assert_eq!; *value += 2; assert_eq!; let value = cell.get_mut_or_init; assert_eq!;fn get_or_try_init<F, E>(self: &Self, f: F) -> Result<&T, E> where F: FnOnce() -> Result<T, E>Gets the contents of the cell, initializing it to
f()if the cell was uninitialized. If the cell was uninitialized andf()failed, an error is returned.Panics
If
f()panics, the panic is propagated to the caller, and the cell remains uninitialized.It is an error to reentrantly initialize the cell from
f. The exact outcome is unspecified. Current implementation deadlocks, but this may be changed to a panic in the future.Examples
use OnceLock; let cell = new; assert_eq!; assert!; let value = cell.get_or_try_init; assert_eq!; assert_eq!fn get_mut_or_try_init<F, E>(self: &mut Self, f: F) -> Result<&mut T, E> where F: FnOnce() -> Result<T, E>Gets the mutable reference of the contents of the cell, initializing it to
f()if the cell was uninitialized. If the cell was uninitialized andf()failed, an error is returned.This method never blocks. Since it borrows the
OnceLockmutably, it is statically guaranteed that no active borrows to theOnceLockexist, including from other threads.Panics
If
f()panics, the panic is propagated to the caller, and the cell remains uninitialized.Examples
use OnceLock; let mut cell: = new; // Failed attempts to initialize the cell do not change its contents assert!; assert!; let value = cell.get_mut_or_try_init; assert_eq!; *value.unwrap += 2; assert_eq!fn into_inner(self: Self) -> Option<T>Consumes the
OnceLock, returning the wrapped value. ReturnsNoneif the cell was uninitialized.Examples
use OnceLock; let cell: = new; assert_eq!; let cell = new; cell.set.unwrap; assert_eq!;fn take(self: &mut Self) -> Option<T>Takes the value out of this
OnceLock, moving it back to an uninitialized state.Has no effect and returns
Noneif theOnceLockwas uninitialized.Since this method borrows the
OnceLockmutably, it is statically guaranteed that no active borrows to theOnceLockexist, including from other threads.Examples
use OnceLock; let mut cell: = new; assert_eq!; let mut cell = new; cell.set.unwrap; assert_eq!; assert_eq!;
impl<T> Any for OnceLock<T>
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for OnceLock<T>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for OnceLock<T>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> CloneToUninit for OnceLock<T>
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> Default for OnceLock<T>
fn default() -> OnceLock<T>Creates a new uninitialized cell.
Example
use OnceLock;
impl<T> Drop for OnceLock<T>
fn drop(self: &mut Self)
impl<T> Freeze for OnceLock<T>
impl<T> From for OnceLock<T>
fn from(t: T) -> TReturns the argument unchanged.
impl<T> From for OnceLock<T>
fn from(value: T) -> SelfCreates a new cell with its contents set to
value.Example
use OnceLock; #
impl<T> From for OnceLock<T>
fn from(t: never) -> T
impl<T> ToOwned for OnceLock<T>
fn to_owned(self: &Self) -> Tfn clone_into(self: &Self, target: &mut T)
impl<T> Unpin for OnceLock<T>
impl<T> UnsafeUnpin for OnceLock<T>
impl<T, U> Into for OnceLock<T>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for OnceLock<T>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for OnceLock<T>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>
impl<T: Clone> Clone for OnceLock<T>
fn clone(self: &Self) -> OnceLock<T>
impl<T: Eq> Eq for OnceLock<T>
impl<T: PartialEq> PartialEq for OnceLock<T>
fn eq(self: &Self, other: &OnceLock<T>) -> boolEquality for two
OnceLocks.Two
OnceLocks are equal if they either both contain values and their values are equal, or if neither contains a value.Examples
use OnceLock; let five = new; five.set.unwrap; let also_five = new; also_five.set.unwrap; assert!; assert!;
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T>
impl<T: Send> Send for OnceLock<T>
impl<T: Sync + Send> Sync for OnceLock<T>
impl<T: UnwindSafe> UnwindSafe for OnceLock<T>
impl<T: fmt::Debug> Debug for OnceLock<T>
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result