blob: 119de8601e00970effe7508c641706e6449dca94 [file] [log] [blame]
/*!
# Overview
`once_cell` provides two new cell-like types, [`unsync::OnceCell`] and [`sync::OnceCell`]. A `OnceCell`
might store arbitrary non-`Copy` types, can be assigned to at most once and provides direct access
to the stored contents. The core API looks *roughly* like this (and there's much more inside, read on!):
```rust,ignore
impl<T> OnceCell<T> {
fn new() -> OnceCell<T> { ... }
fn set(&self, value: T) -> Result<(), T> { ... }
fn get(&self) -> Option<&T> { ... }
}
```
Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires only a shared reference.
Because of the single assignment restriction `get` can return a `&T` instead of `Ref<T>`
or `MutexGuard<T>`.
The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), while the `unsync` one is not.
[`unsync::OnceCell`]: unsync/struct.OnceCell.html
[`sync::OnceCell`]: sync/struct.OnceCell.html
[`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
[`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
# Patterns
`OnceCell` might be useful for a variety of patterns.
## Safe Initialization of global data
```rust
use std::{env, io};
use once_cell::sync::OnceCell;
#[derive(Debug)]
pub struct Logger {
// ...
}
static INSTANCE: OnceCell<Logger> = OnceCell::new();
impl Logger {
pub fn global() -> &'static Logger {
INSTANCE.get().expect("logger is not initialized")
}
fn from_cli(args: env::Args) -> Result<Logger, std::io::Error> {
// ...
# Ok(Logger {})
}
}
fn main() {
let logger = Logger::from_cli(env::args()).unwrap();
INSTANCE.set(logger).unwrap();
// use `Logger::global()` from now on
}
```
## Lazy initialized global data
This is essentially the `lazy_static!` macro, but without a macro.
```rust
use std::{sync::Mutex, collections::HashMap};
use once_cell::sync::OnceCell;
fn global_data() -> &'static Mutex<HashMap<i32, String>> {
static INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new();
INSTANCE.get_or_init(|| {
let mut m = HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
Mutex::new(m)
})
}
```
There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to streamline this pattern:
```rust
use std::{sync::Mutex, collections::HashMap};
use once_cell::sync::Lazy;
static GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
let mut m = HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
Mutex::new(m)
});
fn main() {
println!("{:?}", GLOBAL_DATA.lock().unwrap());
}
```
[`sync::Lazy`]: sync/struct.Lazy.html
[`unsync::Lazy`]: unsync/struct.Lazy.html
## General purpose lazy evaluation
Unlike `lazy_static!`, `Lazy` works with local variables.
```rust
use once_cell::unsync::Lazy;
fn main() {
let ctx = vec![1, 2, 3];
let thunk = Lazy::new(|| {
ctx.iter().sum::<i32>()
});
assert_eq!(*thunk, 6);
}
```
If you need a lazy field in a struct, you probably should use `OnceCell`
directly, because that will allow you to access `self` during initialization.
```rust
use std::{fs, path::PathBuf};
use once_cell::unsync::OnceCell;
struct Ctx {
config_path: PathBuf,
config: OnceCell<String>,
}
impl Ctx {
pub fn get_config(&self) -> Result<&str, std::io::Error> {
let cfg = self.config.get_or_try_init(|| {
fs::read_to_string(&self.config_path)
})?;
Ok(cfg.as_str())
}
}
```
## Building block
Naturally, it is possible to build other abstractions on top of `OnceCell`.
For example, this is a `regex!` macro which takes a string literal and returns an
*expression* that evaluates to a `&'static Regex`:
```
macro_rules! regex {
($re:literal $(,)?) => {{
static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
RE.get_or_init(|| regex::Regex::new($re).unwrap())
}};
}
```
This macro can be useful to avoid the "compile regex on every loop iteration" problem.
Another pattern would be a `LateInit` type for delayed initialization:
```
use once_cell::sync::OnceCell;
#[derive(Debug)]
pub struct LateInit<T> { cell: OnceCell<T> }
impl<T> LateInit<T> {
pub fn init(&self, value: T) {
assert!(self.cell.set(value).is_ok())
}
}
impl<T> Default for LateInit<T> {
fn default() -> Self { LateInit { cell: OnceCell::default() } }
}
impl<T> std::ops::Deref for LateInit<T> {
type Target = T;
fn deref(&self) -> &T {
self.cell.get().unwrap()
}
}
#[derive(Default, Debug)]
struct A<'a> {
b: LateInit<&'a B<'a>>,
}
#[derive(Default, Debug)]
struct B<'a> {
a: LateInit<&'a A<'a>>
}
fn build_cycle() {
let a = A::default();
let b = B::default();
a.b.init(&b);
b.a.init(&a);
println!("{:?}", a.b.a.b.a);
}
```
# Comparison with std
|`!Sync` types | Access Mode | Drawbacks |
|----------------------|------------------------|-----------------------------------------------|
|`Cell<T>` | `T` | requires `T: Copy` for `get` |
|`RefCell<T>` | `RefMut<T>` / `Ref<T>` | may panic at runtime |
|`unsync::OnceCell<T>` | `&T` | assignable only once |
|`Sync` types | Access Mode | Drawbacks |
|----------------------|------------------------|-----------------------------------------------|
|`AtomicT` | `T` | works only with certain `Copy` types |
|`Mutex<T>` | `MutexGuard<T>` | may deadlock at runtime, may block the thread |
|`sync::OnceCell<T>` | `&T` | assignable only once, may block the thread |
Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls
itself. However, because the assignment can happen only once, such cases should be more rare than
equivalents with `RefCell` and `Mutex`.
# Minimum Supported `rustc` Version
This crate's minimum supported `rustc` version is `1.31.1` (or `1.36.0` with the
`parking_lot` feature enabled).
If only the `std` feature is enabled, MSRV will be updated conservatively.
When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable.
In both cases, increasing MSRV is *not* considered a semver-breaking change.
# Implementation details
The implementation is based on the [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/)
and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and [`std::sync::Once`]. In some sense,
`once_cell` just streamlines and unifies those APIs.
To implement a sync flavor of `OnceCell`, this crates uses either a custom re-implementation of
`std::sync::Once` or `parking_lot::Mutex`. This is controlled by the `parking_lot` feature, which
is enabled by default. Performance is the same for both cases, but the `parking_lot` based `OnceCell<T>`
is smaller by up to 16 bytes.
This crate uses `unsafe`.
[`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html
# F.A.Q.
**Should I use lazy_static or once_cell?**
To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static`
and should be preferred.
Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with
`#![no_std]`.
`lazy_static` has received significantly more real world testing, but `once_cell` is also a widely
used crate.
**Should I use the sync or unsync flavor?**
Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where
`sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy
to switch between the two if code becomes multi-threaded later.
At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which
might be easier to debug than a deadlock.
# Related crates
* [double-checked-cell](https://github.com/niklasf/double-checked-cell)
* [lazy-init](https://crates.io/crates/lazy-init)
* [lazycell](https://crates.io/crates/lazycell)
* [mitochondria](https://crates.io/crates/mitochondria)
* [lazy_static](https://crates.io/crates/lazy_static)
*/
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
#[cfg(feature = "parking_lot")]
#[path = "imp_pl.rs"]
mod imp;
#[cfg(feature = "std")]
#[cfg(not(feature = "parking_lot"))]
#[path = "imp_std.rs"]
mod imp;
pub mod unsync {
use core::{
cell::{Cell, UnsafeCell},
fmt, mem,
ops::{Deref, DerefMut},
};
#[cfg(feature = "std")]
use std::panic::{RefUnwindSafe, UnwindSafe};
/// A cell which can be written to only once. It is not thread safe.
///
/// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&`
/// references to the contents.
///
/// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
///
/// # Example
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let cell = OnceCell::new();
/// assert!(cell.get().is_none());
///
/// let value: &String = cell.get_or_init(|| {
/// "Hello, World!".to_string()
/// });
/// assert_eq!(value, "Hello, World!");
/// assert!(cell.get().is_some());
/// ```
pub struct OnceCell<T> {
// Invariant: written to at most once.
inner: UnsafeCell<Option<T>>,
}
// Similarly to a `Sync` bound on `sync::OnceCell`, we can use
// `&unsync::OnceCell` to sneak a `T` through `catch_unwind`,
// by initializing the cell in closure and extracting the value in the
// `Drop`.
#[cfg(feature = "std")]
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
#[cfg(feature = "std")]
impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
impl<T> Default for OnceCell<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.get() {
Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
None => f.write_str("OnceCell(Uninit)"),
}
}
}
impl<T: Clone> Clone for OnceCell<T> {
fn clone(&self) -> OnceCell<T> {
let res = OnceCell::new();
if let Some(value) = self.get() {
match res.set(value.clone()) {
Ok(()) => (),
Err(_) => unreachable!(),
}
}
res
}
}
impl<T: PartialEq> PartialEq for OnceCell<T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T: Eq> Eq for OnceCell<T> {}
impl<T> From<T> for OnceCell<T> {
fn from(value: T) -> Self {
OnceCell { inner: UnsafeCell::new(Some(value)) }
}
}
impl<T> OnceCell<T> {
/// Creates a new empty cell.
pub const fn new() -> OnceCell<T> {
OnceCell { inner: UnsafeCell::new(None) }
}
/// Gets a reference to the underlying value.
///
/// Returns `None` if the cell is empty.
pub fn get(&self) -> Option<&T> {
// Safe due to `inner`'s invariant
unsafe { &*self.inner.get() }.as_ref()
}
/// Gets a mutable reference to the underlying value.
///
/// Returns `None` if the cell is empty.
pub fn get_mut(&mut self) -> Option<&mut T> {
// Safe because we have unique access
unsafe { &mut *self.inner.get() }.as_mut()
}
/// Sets the contents of this cell to `value`.
///
/// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
/// full.
///
/// # Example
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let cell = OnceCell::new();
/// assert!(cell.get().is_none());
///
/// assert_eq!(cell.set(92), Ok(()));
/// assert_eq!(cell.set(62), Err(62));
///
/// assert!(cell.get().is_some());
/// ```
pub fn set(&self, value: T) -> Result<(), T> {
let slot = unsafe { &*self.inner.get() };
if slot.is_some() {
return Err(value);
}
let slot = unsafe { &mut *self.inner.get() };
// This is the only place where we set the slot, no races
// due to reentrancy/concurrency are possible, and we've
// checked that slot is currently `None`, so this write
// maintains the `inner`'s invariant.
*slot = Some(value);
Ok(())
}
/// Gets the contents of the cell, initializing it with `f`
/// if the cell was empty.
///
/// # 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`. Doing
/// so results in a panic.
///
/// # Example
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let cell = OnceCell::new();
/// let value = cell.get_or_init(|| 92);
/// assert_eq!(value, &92);
/// let value = cell.get_or_init(|| unreachable!());
/// assert_eq!(value, &92);
/// ```
pub fn get_or_init<F>(&self, f: F) -> &T
where
F: FnOnce() -> T,
{
enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
Ok(val) => val,
Err(void) => match void {},
}
}
/// Gets the contents of the cell, initializing it with `f` if
/// the cell was empty. If the cell was empty and `f` 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`. Doing
/// so results in a panic.
///
/// # Example
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let cell = OnceCell::new();
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
/// assert!(cell.get().is_none());
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
/// Ok(92)
/// });
/// assert_eq!(value, Ok(&92));
/// assert_eq!(cell.get(), Some(&92))
/// ```
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
where
F: FnOnce() -> Result<T, E>,
{
if let Some(val) = self.get() {
return Ok(val);
}
let val = f()?;
// Note that *some* forms of reentrant initialization might lead to
// UB (see `reentrant_init` test). I believe that just removing this
// `assert`, while keeping `set/get` would be sound, but it seems
// better to panic, rather than to silently use an old value.
assert!(self.set(val).is_ok(), "reentrant init");
Ok(self.get().unwrap())
}
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
///
/// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
///
/// # Examples
///
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let mut cell: OnceCell<String> = OnceCell::new();
/// assert_eq!(cell.take(), None);
///
/// let mut cell = OnceCell::new();
/// cell.set("hello".to_string()).unwrap();
/// assert_eq!(cell.take(), Some("hello".to_string()));
/// assert_eq!(cell.get(), None);
/// ```
pub fn take(&mut self) -> Option<T> {
mem::replace(self, Self::default()).into_inner()
}
/// Consumes the `OnceCell`, returning the wrapped value.
///
/// Returns `None` if the cell was empty.
///
/// # Examples
///
/// ```
/// use once_cell::unsync::OnceCell;
///
/// let cell: OnceCell<String> = OnceCell::new();
/// assert_eq!(cell.into_inner(), None);
///
/// let cell = OnceCell::new();
/// cell.set("hello".to_string()).unwrap();
/// assert_eq!(cell.into_inner(), Some("hello".to_string()));
/// ```
pub fn into_inner(self) -> Option<T> {
// Because `into_inner` takes `self` by value, the compiler statically verifies
// that it is not currently borrowed. So it is safe to move out `Option<T>`.
self.inner.into_inner()
}
}
/// A value which is initialized on the first access.
///
/// # Example
/// ```
/// use once_cell::unsync::Lazy;
///
/// let lazy: Lazy<i32> = Lazy::new(|| {
/// println!("initializing");
/// 92
/// });
/// println!("ready");
/// println!("{}", *lazy);
/// println!("{}", *lazy);
///
/// // Prints:
/// // ready
/// // initializing
/// // 92
/// // 92
/// ```
pub struct Lazy<T, F = fn() -> T> {
cell: OnceCell<T>,
init: Cell<Option<F>>,
}
#[cfg(feature = "std")]
impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
}
}
impl<T, F> Lazy<T, F> {
/// Creates a new lazy value with the given initializing function.
///
/// # Example
/// ```
/// # fn main() {
/// use once_cell::unsync::Lazy;
///
/// let hello = "Hello, World!".to_string();
///
/// let lazy = Lazy::new(|| hello.to_uppercase());
///
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// # }
/// ```
pub const fn new(init: F) -> Lazy<T, F> {
Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) }
}
}
impl<T, F: FnOnce() -> T> Lazy<T, F> {
/// Forces the evaluation of this lazy value and returns a reference to
/// the result.
///
/// This is equivalent to the `Deref` impl, but is explicit.
///
/// # Example
/// ```
/// use once_cell::unsync::Lazy;
///
/// let lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::force(&lazy), &92);
/// assert_eq!(&*lazy, &92);
/// ```
pub fn force(this: &Lazy<T, F>) -> &T {
this.cell.get_or_init(|| match this.init.take() {
Some(f) => f(),
None => panic!("Lazy instance has previously been poisoned"),
})
}
}
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
type Target = T;
fn deref(&self) -> &T {
Lazy::force(self)
}
}
impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
Lazy::force(self);
self.cell.get_mut().unwrap_or_else(|| unreachable!())
}
}
impl<T: Default> Default for Lazy<T> {
/// Creates a new lazy value using `Default` as the initializing function.
fn default() -> Lazy<T> {
Lazy::new(T::default)
}
}
}
#[cfg(feature = "std")]
pub mod sync {
use std::{
cell::Cell,
fmt, mem,
ops::{Deref, DerefMut},
panic::RefUnwindSafe,
};
use crate::imp::OnceCell as Imp;
/// A thread-safe cell which can be written to only once.
///
/// `OnceCell` provides `&` references to the contents without RAII guards.
///
/// Reading a non-`None` value out of `OnceCell` establishes a
/// happens-before relationship with a corresponding write. For example, if
/// thread A initializes the cell with `get_or_init(f)`, and thread B
/// subsequently reads the result of this call, B also observes all the side
/// effects of `f`.
///
/// # Example
/// ```
/// use once_cell::sync::OnceCell;
///
/// static CELL: OnceCell<String> = OnceCell::new();
/// assert!(CELL.get().is_none());
///
/// std::thread::spawn(|| {
/// let value: &String = CELL.get_or_init(|| {
/// "Hello, World!".to_string()
/// });
/// assert_eq!(value, "Hello, World!");
/// }).join().unwrap();
///
/// let value: Option<&String> = CELL.get();
/// assert!(value.is_some());
/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
/// ```
pub struct OnceCell<T>(Imp<T>);
impl<T> Default for OnceCell<T> {
fn default() -> OnceCell<T> {
OnceCell::new()
}
}
impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.get() {
Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
None => f.write_str("OnceCell(Uninit)"),
}
}
}
impl<T: Clone> Clone for OnceCell<T> {
fn clone(&self) -> OnceCell<T> {
let res = OnceCell::new();
if let Some(value) = self.get() {
match res.set(value.clone()) {
Ok(()) => (),
Err(_) => unreachable!(),
}
}
res
}
}
impl<T> From<T> for OnceCell<T> {
fn from(value: T) -> Self {
let cell = Self::new();
cell.get_or_init(|| value);
cell
}
}
impl<T: PartialEq> PartialEq for OnceCell<T> {
fn eq(&self, other: &OnceCell<T>) -> bool {
self.get() == other.get()
}
}
impl<T: Eq> Eq for OnceCell<T> {}
impl<T> OnceCell<T> {
/// Creates a new empty cell.
pub const fn new() -> OnceCell<T> {
OnceCell(Imp::new())
}
/// Gets the reference to the underlying value.
///
/// Returns `None` if the cell is empty, or being initialized. This
/// method never blocks.
pub fn get(&self) -> Option<&T> {
if self.0.is_initialized() {
// Safe b/c value is initialized.
Some(unsafe { self.get_unchecked() })
} else {
None
}
}
/// Gets the mutable reference to the underlying value.
///
/// Returns `None` if the cell is empty.
pub fn get_mut(&mut self) -> Option<&mut T> {
self.0.get_mut()
}
/// Get the reference to the underlying value, without checking if the
/// cell is initialized.
///
/// # Safety
///
/// Caller must ensure that the cell is in initialized state, and that
/// the contents are acquired by (synchronized to) this thread.
pub unsafe fn get_unchecked(&self) -> &T {
self.0.get_unchecked()
}
/// Sets the contents of this cell to `value`.
///
/// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
/// full.
///
/// # Example
///
/// ```
/// use once_cell::sync::OnceCell;
///
/// static CELL: OnceCell<i32> = OnceCell::new();
///
/// fn main() {
/// assert!(CELL.get().is_none());
///
/// std::thread::spawn(|| {
/// assert_eq!(CELL.set(92), Ok(()));
/// }).join().unwrap();
///
/// assert_eq!(CELL.set(62), Err(62));
/// assert_eq!(CELL.get(), Some(&92));
/// }
/// ```
pub fn set(&self, value: T) -> Result<(), T> {
let mut value = Some(value);
self.get_or_init(|| value.take().unwrap());
match value {
None => Ok(()),
Some(value) => Err(value),
}
}
/// Gets the contents of the cell, initializing it with `f` if the cell
/// was empty.
///
/// Many threads may call `get_or_init` concurrently with different
/// initializing functions, but it is guaranteed that only one function
/// will be executed.
///
/// # 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.
///
/// # Example
/// ```
/// use once_cell::sync::OnceCell;
///
/// let cell = OnceCell::new();
/// let value = cell.get_or_init(|| 92);
/// assert_eq!(value, &92);
/// let value = cell.get_or_init(|| unreachable!());
/// assert_eq!(value, &92);
/// ```
pub fn get_or_init<F>(&self, f: F) -> &T
where
F: FnOnce() -> T,
{
enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
Ok(val) => val,
Err(void) => match void {},
}
}
/// Gets the contents of the cell, initializing it with `f` if
/// the cell was empty. If the cell was empty and `f` 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.
///
/// # Example
/// ```
/// use once_cell::sync::OnceCell;
///
/// let cell = OnceCell::new();
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
/// assert!(cell.get().is_none());
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
/// Ok(92)
/// });
/// assert_eq!(value, Ok(&92));
/// assert_eq!(cell.get(), Some(&92))
/// ```
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
where
F: FnOnce() -> Result<T, E>,
{
// Fast path check
if let Some(value) = self.get() {
return Ok(value);
}
self.0.initialize(f)?;
// Safe b/c value is initialized.
debug_assert!(self.0.is_initialized());
Ok(unsafe { self.get_unchecked() })
}
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
///
/// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
///
/// # Examples
///
/// ```
/// use once_cell::sync::OnceCell;
///
/// let mut cell: OnceCell<String> = OnceCell::new();
/// assert_eq!(cell.take(), None);
///
/// let mut cell = OnceCell::new();
/// cell.set("hello".to_string()).unwrap();
/// assert_eq!(cell.take(), Some("hello".to_string()));
/// assert_eq!(cell.get(), None);
/// ```
pub fn take(&mut self) -> Option<T> {
mem::replace(self, Self::default()).into_inner()
}
/// Consumes the `OnceCell`, returning the wrapped value. Returns
/// `None` if the cell was empty.
///
/// # Examples
///
/// ```
/// use once_cell::sync::OnceCell;
///
/// let cell: OnceCell<String> = OnceCell::new();
/// assert_eq!(cell.into_inner(), None);
///
/// let cell = OnceCell::new();
/// cell.set("hello".to_string()).unwrap();
/// assert_eq!(cell.into_inner(), Some("hello".to_string()));
/// ```
pub fn into_inner(self) -> Option<T> {
self.0.into_inner()
}
}
/// A value which is initialized on the first access.
///
/// This type is thread-safe and can be used in statics.
///
/// # Example
///
/// ```
/// use std::collections::HashMap;
///
/// use once_cell::sync::Lazy;
///
/// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::new(|| {
/// println!("initializing");
/// let mut m = HashMap::new();
/// m.insert(13, "Spica".to_string());
/// m.insert(74, "Hoyten".to_string());
/// m
/// });
///
/// fn main() {
/// println!("ready");
/// std::thread::spawn(|| {
/// println!("{:?}", HASHMAP.get(&13));
/// }).join().unwrap();
/// println!("{:?}", HASHMAP.get(&74));
///
/// // Prints:
/// // ready
/// // initializing
/// // Some("Spica")
/// // Some("Hoyten")
/// }
/// ```
pub struct Lazy<T, F = fn() -> T> {
cell: OnceCell<T>,
init: Cell<Option<F>>,
}
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
}
}
// We never create a `&F` from a `&Lazy<T, F>` so it is fine
// to not impl `Sync` for `F`
// we do create a `&mut Option<F>` in `force`, but this is
// properly synchronized, so it only happens once
// so it also does not contribute to this impl.
unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
// auto-derived `Send` impl is OK.
#[cfg(feature = "std")]
impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
impl<T, F> Lazy<T, F> {
/// Creates a new lazy value with the given initializing
/// function.
pub const fn new(f: F) -> Lazy<T, F> {
Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) }
}
}
impl<T, F: FnOnce() -> T> Lazy<T, F> {
/// Forces the evaluation of this lazy value and
/// returns a reference to the result. This is equivalent
/// to the `Deref` impl, but is explicit.
///
/// # Example
/// ```
/// use once_cell::sync::Lazy;
///
/// let lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::force(&lazy), &92);
/// assert_eq!(&*lazy, &92);
/// ```
pub fn force(this: &Lazy<T, F>) -> &T {
this.cell.get_or_init(|| match this.init.take() {
Some(f) => f(),
None => panic!("Lazy instance has previously been poisoned"),
})
}
}
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
type Target = T;
fn deref(&self) -> &T {
Lazy::force(self)
}
}
impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
Lazy::force(self);
self.cell.get_mut().unwrap_or_else(|| unreachable!())
}
}
impl<T: Default> Default for Lazy<T> {
/// Creates a new lazy value using `Default` as the initializing function.
fn default() -> Lazy<T> {
Lazy::new(T::default)
}
}
/// ```compile_fail
/// struct S(*mut ());
/// unsafe impl Sync for S {}
///
/// fn share<T: Sync>(_: &T) {}
/// share(&once_cell::sync::OnceCell::<S>::new());
/// ```
///
/// ```compile_fail
/// struct S(*mut ());
/// unsafe impl Sync for S {}
///
/// fn share<T: Sync>(_: &T) {}
/// share(&once_cell::sync::Lazy::<S>::new(|| unimplemented!()));
/// ```
fn _dummy() {}
}
/// "First one wins" flavor of `OnceCell`.
///
/// If two threads race to initialize a type from the `race` module, they
/// don't block, execute initialization function together, but only one of
/// them stores the result.
///
/// This module does not require `std` feature.
#[cfg(feature = "unstable")]
pub mod race {
use core::{
num::NonZeroUsize,
sync::atomic::{AtomicUsize, Ordering},
};
#[cfg(feature = "std")]
use std::{marker::PhantomData, ptr, sync::atomic::AtomicPtr};
#[derive(Default, Debug)]
pub struct OnceNonZeroUsize {
inner: AtomicUsize,
}
impl OnceNonZeroUsize {
pub const fn new() -> OnceNonZeroUsize {
OnceNonZeroUsize { inner: AtomicUsize::new(0) }
}
pub fn get(&self) -> Option<NonZeroUsize> {
let val = self.inner.load(Ordering::Acquire);
NonZeroUsize::new(val)
}
pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> {
let val = self.inner.compare_and_swap(0, value.get(), Ordering::AcqRel);
if val == 0 {
Ok(())
} else {
Err(())
}
}
pub fn get_or_init<F>(&self, f: F) -> NonZeroUsize
where
F: FnOnce() -> NonZeroUsize,
{
enum Void {}
match self.get_or_try_init(|| Ok::<NonZeroUsize, Void>(f())) {
Ok(val) => val,
Err(void) => match void {},
}
}
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<NonZeroUsize, E>
where
F: FnOnce() -> Result<NonZeroUsize, E>,
{
let val = self.inner.load(Ordering::Acquire);
let res = match NonZeroUsize::new(val) {
Some(it) => it,
None => {
let mut val = f()?.get();
let old_val = self.inner.compare_and_swap(0, val, Ordering::AcqRel);
if old_val != 0 {
val = old_val;
}
unsafe { NonZeroUsize::new_unchecked(val) }
}
};
Ok(res)
}
}
#[derive(Default, Debug)]
pub struct OnceBool {
inner: OnceNonZeroUsize,
}
impl OnceBool {
fn from_usize(value: NonZeroUsize) -> bool {
value.get() == 1
}
fn to_usize(value: bool) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked(if value { 1 } else { 2 }) }
}
pub const fn new() -> OnceBool {
OnceBool { inner: OnceNonZeroUsize::new() }
}
pub fn get(&self) -> Option<bool> {
self.inner.get().map(OnceBool::from_usize)
}
pub fn set(&self, value: bool) -> Result<(), ()> {
self.inner.set(OnceBool::to_usize(value))
}
pub fn get_or_init<F>(&self, f: F) -> bool
where
F: FnOnce() -> bool,
{
OnceBool::from_usize(self.inner.get_or_init(|| OnceBool::to_usize(f())))
}
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<bool, E>
where
F: FnOnce() -> Result<bool, E>,
{
self.inner.get_or_try_init(|| f().map(OnceBool::to_usize)).map(OnceBool::from_usize)
}
}
#[derive(Default, Debug)]
#[cfg(feature = "std")]
pub struct OnceBox<T> {
inner: AtomicPtr<T>,
ghost: PhantomData<Option<Box<T>>>,
}
#[cfg(feature = "std")]
impl<T> Drop for OnceBox<T> {
fn drop(&mut self) {
let ptr = *self.inner.get_mut();
if !ptr.is_null() {
drop(unsafe { Box::from_raw(ptr) })
}
}
}
#[cfg(feature = "std")]
impl<T> OnceBox<T> {
pub const fn new() -> OnceBox<T> {
OnceBox { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData }
}
pub fn get(&self) -> Option<&T> {
let ptr = self.inner.load(Ordering::Acquire);
if ptr.is_null() {
return None;
}
Some(unsafe { &*ptr })
}
// Result<(), Box<T>> here?
pub fn set(&self, value: T) -> Result<(), ()> {
let ptr = Box::into_raw(Box::new(value));
if ptr.is_null() {
drop(unsafe { Box::from_raw(ptr) });
return Err(());
}
Ok(())
}
pub fn get_or_init<F>(&self, f: F) -> &T
where
F: FnOnce() -> T,
{
enum Void {}
match self.get_or_try_init(|| Ok::<T, Void>(f())) {
Ok(val) => val,
Err(void) => match void {},
}
}
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
where
F: FnOnce() -> Result<T, E>,
{
let mut ptr = self.inner.load(Ordering::Acquire);
if ptr.is_null() {
let val = f()?;
ptr = Box::into_raw(Box::new(val));
let old_ptr = self.inner.compare_and_swap(ptr::null_mut(), ptr, Ordering::AcqRel);
if !old_ptr.is_null() {
drop(unsafe { Box::from_raw(ptr) });
ptr = old_ptr;
}
};
Ok(unsafe { &*ptr })
}
}
/// ```compile_fail
/// struct S(*mut ());
/// unsafe impl Sync for S {}
///
/// fn share<T: Sync>(_: &T) {}
/// share(&once_cell::race::OnceBox::<S>::new());
/// ```
#[cfg(feature = "std")]
unsafe impl<T: Sync + Send> Sync for OnceBox<T> {}
}