pub struct LazyLock<T, F = fn() -> T> { /* private fields */ }
Expand description
A value which is initialized on the first access.
This type is a thread-safe LazyCell
, and can be used in statics.
Since initialization may be called from multiple threads, any
dereferencing call will block the calling thread if another
initialization routine is currently running.
§Poisoning
If the initialization closure passed to LazyLock::new
panics, the lock will be poisoned.
Once the lock is poisoned, any threads that attempt to access this lock (via a dereference
or via an explicit call to force()
) will panic.
This concept is similar to that of poisoning in the std::sync::poison
module. A key
difference, however, is that poisoning in LazyLock
is unrecoverable. All future accesses of
the lock from other threads will panic, whereas a type in std::sync::poison
like
std::sync::poison::Mutex
allows recovery via PoisonError::into_inner()
.
§Examples
Initialize static variables with LazyLock
.
use std::sync::LazyLock;
// Note: static items do not call [`Drop`] on program termination, so this won't be deallocated.
// this is fine, as the OS can deallocate the terminated program faster than we can free memory
// but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional.
static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| {
// M3 Ultra takes about 16 million years in --release config
another_crate::great_question()
});
// The `String` is built, stored in the `LazyLock`, and returned as `&String`.
let _ = &*DEEP_THOUGHT;
Initialize fields with LazyLock
.
use std::sync::LazyLock;
#[derive(Debug)]
struct UseCellLock {
number: LazyLock<u32>,
}
fn main() {
let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
let data = UseCellLock { number: lock };
println!("{}", *data.number);
}
Implementations§
Source§impl<T, F> LazyLock<T, F>where
F: FnOnce() -> T,
impl<T, F> LazyLock<T, F>where
F: FnOnce() -> T,
1.80.0 (const: 1.80.0) · Sourcepub const fn new(f: F) -> LazyLock<T, F>
Available on crate feature std
only.
pub const fn new(f: F) -> LazyLock<T, F>
std
only.Creates a new lazy value with the given initializing function.
§Examples
use std::sync::LazyLock;
let hello = "Hello, World!".to_string();
let lazy = LazyLock::new(|| hello.to_uppercase());
assert_eq!(&*lazy, "HELLO, WORLD!");
Sourcepub fn into_inner(this: LazyLock<T, F>) -> Result<T, F>
🔬This is a nightly-only experimental API. (lazy_cell_into_inner
)Available on crate feature std
only.
pub fn into_inner(this: LazyLock<T, F>) -> Result<T, F>
lazy_cell_into_inner
)std
only.Consumes this LazyLock
returning the stored value.
Returns Ok(value)
if Lazy
is initialized and Err(f)
otherwise.
§Panics
Panics if the lock is poisoned.
§Examples
#![feature(lazy_cell_into_inner)]
use std::sync::LazyLock;
let hello = "Hello, World!".to_string();
let lazy = LazyLock::new(|| hello.to_uppercase());
assert_eq!(&*lazy, "HELLO, WORLD!");
assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
Sourcepub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T
🔬This is a nightly-only experimental API. (lazy_get
)Available on crate feature std
only.
pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T
lazy_get
)std
only.Forces the evaluation of this lazy value and returns a mutable reference to the result.
§Panics
If the initialization closure panics (the one that is passed to the new()
method), the
panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
accesses of the lock (via force()
or a dereference) to panic.
§Examples
#![feature(lazy_get)]
use std::sync::LazyLock;
let mut lazy = LazyLock::new(|| 92);
let p = LazyLock::force_mut(&mut lazy);
assert_eq!(*p, 92);
*p = 44;
assert_eq!(*lazy, 44);
1.80.0 · Sourcepub fn force(this: &LazyLock<T, F>) -> &T
Available on crate feature std
only.
pub fn force(this: &LazyLock<T, F>) -> &T
std
only.Forces the evaluation of this lazy value and returns a reference to
result. This is equivalent to the Deref
impl, but is explicit.
This method will block the calling thread if another initialization routine is currently running.
§Panics
If the initialization closure panics (the one that is passed to the new()
method), the
panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
accesses of the lock (via force()
or a dereference) to panic.
§Examples
use std::sync::LazyLock;
let lazy = LazyLock::new(|| 92);
assert_eq!(LazyLock::force(&lazy), &92);
assert_eq!(&*lazy, &92);
Source§impl<T, F> LazyLock<T, F>
impl<T, F> LazyLock<T, F>
Sourcepub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T>
🔬This is a nightly-only experimental API. (lazy_get
)Available on crate feature std
only.
pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T>
lazy_get
)std
only.Returns a mutable reference to the value if initialized. Otherwise (if uninitialized or
poisoned), returns None
.
§Examples
#![feature(lazy_get)]
use std::sync::LazyLock;
let mut lazy = LazyLock::new(|| 92);
assert_eq!(LazyLock::get_mut(&mut lazy), None);
let _ = LazyLock::force(&lazy);
*LazyLock::get_mut(&mut lazy).unwrap() = 44;
assert_eq!(*lazy, 44);
Sourcepub fn get(this: &LazyLock<T, F>) -> Option<&T>
🔬This is a nightly-only experimental API. (lazy_get
)Available on crate feature std
only.
pub fn get(this: &LazyLock<T, F>) -> Option<&T>
lazy_get
)std
only.Returns a reference to the value if initialized. Otherwise (if uninitialized or poisoned),
returns None
.
§Examples
#![feature(lazy_get)]
use std::sync::LazyLock;
let lazy = LazyLock::new(|| 92);
assert_eq!(LazyLock::get(&lazy), None);
let _ = LazyLock::force(&lazy);
assert_eq!(LazyLock::get(&lazy), Some(&92));
Trait Implementations§
1.80.0 · Source§impl<T, F> Deref for LazyLock<T, F>where
F: FnOnce() -> T,
impl<T, F> Deref for LazyLock<T, F>where
F: FnOnce() -> T,
Source§fn deref(&self) -> &T
fn deref(&self) -> &T
Dereferences the value.
This method will block the calling thread if another initialization routine is currently running.
§Panics
If the initialization closure panics (the one that is passed to the new()
method), the
panic is propagated to the caller, and the lock becomes poisoned. This will cause all future
accesses of the lock (via force()
or a dereference) to panic.
impl<T, F> RefUnwindSafe for LazyLock<T, F>
impl<T, F> Sync for LazyLock<T, F>
impl<T, F> UnwindSafe for LazyLock<T, F>where
T: UnwindSafe,
F: UnwindSafe,
Auto Trait Implementations§
impl<T, F = fn() -> T> !Freeze for LazyLock<T, F>
impl<T, F> Send for LazyLock<T, F>
impl<T, F> Unpin for LazyLock<T, F>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.