//! Lazy values and one-time initialization of static data. use crate::{ cell::{Cell, UnsafeCell}, fmt, mem::{self, MaybeUninit}, ops::{Deref, Drop}, panic::{RefUnwindSafe, UnwindSafe}, sync::Once, }; #[doc(inline)] #[unstable(feature = "once_cell", issue = "74465")] pub use core::lazy::*; /// A synchronization primitive which can be written to only once. /// /// This type is a thread-safe `OnceCell`. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// static CELL: SyncOnceCell = SyncOnceCell::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!"); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub struct SyncOnceCell { once: Once, // Whether or not the value is initialized is tracked by `state_and_queue`. value: UnsafeCell>, } // Why do we need `T: Send`? // Thread A creates a `SyncOnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. #[unstable(feature = "once_cell", issue = "74465")] unsafe impl Sync for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] unsafe impl Send for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl RefUnwindSafe for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl UnwindSafe for SyncOnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl Default for SyncOnceCell { fn default() -> SyncOnceCell { SyncOnceCell::new() } } #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for SyncOnceCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("Once").field(v).finish(), None => f.write_str("Once(Uninit)"), } } } #[unstable(feature = "once_cell", issue = "74465")] impl Clone for SyncOnceCell { fn clone(&self) -> SyncOnceCell { let cell = Self::new(); if let Some(value) = self.get() { match cell.set(value.clone()) { Ok(()) => (), Err(_) => unreachable!(), } } cell } } #[unstable(feature = "once_cell", issue = "74465")] impl From for SyncOnceCell { fn from(value: T) -> Self { let cell = Self::new(); match cell.set(value) { Ok(()) => cell, Err(_) => unreachable!(), } } } #[unstable(feature = "once_cell", issue = "74465")] impl PartialEq for SyncOnceCell { fn eq(&self, other: &SyncOnceCell) -> bool { self.get() == other.get() } } #[unstable(feature = "once_cell", issue = "74465")] impl Eq for SyncOnceCell {} impl SyncOnceCell { /// Creates a new empty cell. #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> SyncOnceCell { SyncOnceCell { once: Once::new(), value: UnsafeCell::new(MaybeUninit::uninit()) } } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized Some(unsafe { self.get_unchecked() }) } else { None } } /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. This method never blocks. #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { if self.is_initialized() { // Safe b/c checked is_initialized and we have a unique access Some(unsafe { self.get_unchecked_mut() }) } else { None } } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell's value was updated. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// static CELL: SyncOnceCell = SyncOnceCell::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)); /// } /// ``` #[unstable(feature = "once_cell", issue = "74465")] 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. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// let cell = SyncOnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, } } /// 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. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// let cell = SyncOnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { // Fast path check // NOTE: We need to perform an acquire on the state in this method // in order to correctly synchronize `SyncLazy::force`. This is // currently done by calling `self.get()`, which in turn calls // `self.is_initialized()`, which in turn performs the acquire. if let Some(value) = self.get() { return Ok(value); } self.initialize(f)?; debug_assert!(self.is_initialized()); // Safety: The inner value has been initialized Ok(unsafe { self.get_unchecked() }) } /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns /// `None` if the cell was empty. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// let cell: SyncOnceCell = SyncOnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = SyncOnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(mut self) -> Option { // Safety: Safe because we immediately free `self` without dropping let inner = unsafe { self.take_inner() }; // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set // the state to uninitialized. mem::ManuallyDrop::new(self); inner } /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized. /// /// Safety is guaranteed by requiring a mutable reference. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncOnceCell; /// /// let mut cell: SyncOnceCell = SyncOnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = SyncOnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option { mem::take(self).into_inner() } /// Takes the wrapped value out of a `SyncOnceCell`. /// Afterwards the cell is no longer initialized. /// /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell /// are valid. Only used by `into_inner` and `drop`. unsafe fn take_inner(&mut self) -> Option { // The mutable reference guarantees there are no other threads that can observe us // taking out the wrapped value. // Right after this function `self` is supposed to be freed, so it makes little sense // to atomically set the state to uninitialized. if self.is_initialized() { let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit())); Some(value.into_inner().assume_init()) } else { None } } #[inline] fn is_initialized(&self) -> bool { self.once.is_completed() } #[cold] fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { let mut res: Result<(), E> = Ok(()); let slot = &self.value; // Ignore poisoning from other threads // If another thread panics, then we'll be able to run our closure self.once.call_once_force(|p| { match f() { Ok(value) => { unsafe { (&mut *slot.get()).write(value) }; } Err(e) => { res = Err(e); // Treat the underlying `Once` as poisoned since we // failed to initialize our value. Calls p.poison(); } } }); res } /// Safety: The value must be initialized unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); (&*self.value.get()).get_ref() } /// Safety: The value must be initialized unsafe fn get_unchecked_mut(&mut self) -> &mut T { debug_assert!(self.is_initialized()); (&mut *self.value.get()).get_mut() } } impl Drop for SyncOnceCell { fn drop(&mut self) { // Safety: The cell is being dropped, so it can't be accessed again unsafe { self.take_inner() }; } } /// A value which is initialized on the first access. /// /// This type is a thread-safe `Lazy`, and can be used in statics. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::collections::HashMap; /// /// use std::lazy::SyncLazy; /// /// static HASHMAP: SyncLazy> = SyncLazy::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") /// } /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub struct SyncLazy T> { cell: SyncOnceCell, init: Cell>, } #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for SyncLazy { 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 `&SyncLazy` so it is fine // to not impl `Sync` for `F` // we do create a `&mut Option` in `force`, but this is // properly synchronized, so it only happens once // so it also does not contribute to this impl. #[unstable(feature = "once_cell", issue = "74465")] unsafe impl Sync for SyncLazy where SyncOnceCell: Sync {} // auto-derived `Send` impl is OK. #[unstable(feature = "once_cell", issue = "74465")] impl RefUnwindSafe for SyncLazy where SyncOnceCell: RefUnwindSafe {} #[unstable(feature = "once_cell", issue = "74465")] impl UnwindSafe for SyncLazy where SyncOnceCell: UnwindSafe {} impl SyncLazy { /// Creates a new lazy value with the given initializing /// function. #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(f: F) -> SyncLazy { SyncLazy { cell: SyncOnceCell::new(), init: Cell::new(Some(f)) } } } impl T> SyncLazy { /// Forces the evaluation of this lazy value and /// returns a reference to result. This is equivalent /// to the `Deref` impl, but is explicit. /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::lazy::SyncLazy; /// /// let lazy = SyncLazy::new(|| 92); /// /// assert_eq!(SyncLazy::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &SyncLazy) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) } } #[unstable(feature = "once_cell", issue = "74465")] impl T> Deref for SyncLazy { type Target = T; fn deref(&self) -> &T { SyncLazy::force(self) } } #[unstable(feature = "once_cell", issue = "74465")] impl Default for SyncLazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> SyncLazy { SyncLazy::new(T::default) } } #[cfg(test)] mod tests { use crate::{ lazy::{Lazy, SyncLazy, SyncOnceCell}, panic, sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, mpsc::channel, Mutex, }, }; #[test] fn lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: Lazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn lazy_poisoning() { let x: Lazy = Lazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len())); assert!(res.is_err()); } } // miri doesn't support threads #[cfg(not(miri))] fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { crate::thread::spawn(f).join().unwrap() } #[cfg(not(miri))] fn spawn(f: impl FnOnce() + Send + 'static) { let _ = crate::thread::spawn(f); } // "stub threads" for Miri #[cfg(miri)] fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { f(()) } #[cfg(miri)] fn spawn(f: impl FnOnce() + Send + 'static) { f(()) } #[test] fn sync_once_cell() { static ONCE_CELL: SyncOnceCell = SyncOnceCell::new(); assert!(ONCE_CELL.get().is_none()); spawn_and_wait(|| { ONCE_CELL.get_or_init(|| 92); assert_eq!(ONCE_CELL.get(), Some(&92)); }); ONCE_CELL.get_or_init(|| panic!("Kabom!")); assert_eq!(ONCE_CELL.get(), Some(&92)); } #[test] fn sync_once_cell_get_mut() { let mut c = SyncOnceCell::new(); assert!(c.get_mut().is_none()); c.set(90).unwrap(); *c.get_mut().unwrap() += 2; assert_eq!(c.get_mut(), Some(&mut 92)); } #[test] fn sync_once_cell_get_unchecked() { let c = SyncOnceCell::new(); c.set(92).unwrap(); unsafe { assert_eq!(c.get_unchecked(), &92); } } #[test] fn sync_once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); struct Dropper; impl Drop for Dropper { fn drop(&mut self) { DROP_CNT.fetch_add(1, SeqCst); } } let x = SyncOnceCell::new(); spawn_and_wait(move || { x.get_or_init(|| Dropper); assert_eq!(DROP_CNT.load(SeqCst), 0); drop(x); }); assert_eq!(DROP_CNT.load(SeqCst), 1); } #[test] fn sync_once_cell_drop_empty() { let x = SyncOnceCell::::new(); drop(x); } #[test] fn clone() { let s = SyncOnceCell::new(); let c = s.clone(); assert!(c.get().is_none()); s.set("hello".to_string()).unwrap(); let c = s.clone(); assert_eq!(c.get().map(String::as_str), Some("hello")); } #[test] fn get_or_try_init() { let cell: SyncOnceCell = SyncOnceCell::new(); assert!(cell.get().is_none()); let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); assert!(!cell.is_initialized()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert_eq!( cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string()) ); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[test] fn from_impl() { assert_eq!(SyncOnceCell::from("value").get(), Some(&"value")); assert_ne!(SyncOnceCell::from("foo").get(), Some(&"bar")); } #[test] fn partialeq_impl() { assert!(SyncOnceCell::from("value") == SyncOnceCell::from("value")); assert!(SyncOnceCell::from("foo") != SyncOnceCell::from("bar")); assert!(SyncOnceCell::::new() == SyncOnceCell::new()); assert!(SyncOnceCell::::new() != SyncOnceCell::from("value".to_owned())); } #[test] fn into_inner() { let cell: SyncOnceCell = SyncOnceCell::new(); assert_eq!(cell.into_inner(), None); let cell = SyncOnceCell::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); } #[test] fn sync_lazy_new() { static CALLED: AtomicUsize = AtomicUsize::new(0); static SYNC_LAZY: SyncLazy = SyncLazy::new(|| { CALLED.fetch_add(1, SeqCst); 92 }); assert_eq!(CALLED.load(SeqCst), 0); spawn_and_wait(|| { let y = *SYNC_LAZY - 30; assert_eq!(y, 62); assert_eq!(CALLED.load(SeqCst), 1); }); let y = *SYNC_LAZY - 30; assert_eq!(y, 62); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn sync_lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: SyncLazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] #[cfg_attr(miri, ignore)] // leaks memory fn static_sync_lazy() { static XS: SyncLazy> = SyncLazy::new(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }); spawn_and_wait(|| { assert_eq!(&*XS, &vec![1, 2, 3]); }); assert_eq!(&*XS, &vec![1, 2, 3]); } #[test] #[cfg_attr(miri, ignore)] // leaks memory fn static_sync_lazy_via_fn() { fn xs() -> &'static Vec { static XS: SyncOnceCell> = SyncOnceCell::new(); XS.get_or_init(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }) } assert_eq!(xs(), &vec![1, 2, 3]); } #[test] fn sync_lazy_poisoning() { let x: SyncLazy = SyncLazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = panic::catch_unwind(|| x.len()); assert!(res.is_err()); } } #[test] fn is_sync_send() { fn assert_traits() {} assert_traits::>(); assert_traits::>(); } #[test] fn eval_once_macro() { macro_rules! eval_once { (|| -> $ty:ty { $($body:tt)* }) => {{ static ONCE_CELL: SyncOnceCell<$ty> = SyncOnceCell::new(); fn init() -> $ty { $($body)* } ONCE_CELL.get_or_init(init) }}; } let fib: &'static Vec = eval_once! { || -> Vec { let mut res = vec![1, 1]; for i in 0..10 { let next = res[i] + res[i + 1]; res.push(next); } res } }; assert_eq!(fib[5], 8) } #[test] #[cfg_attr(miri, ignore)] // deadlocks without real threads fn sync_once_cell_does_not_leak_partially_constructed_boxes() { static ONCE_CELL: SyncOnceCell = SyncOnceCell::new(); let n_readers = 10; let n_writers = 3; const MSG: &str = "Hello, World"; let (tx, rx) = channel(); for _ in 0..n_readers { let tx = tx.clone(); spawn(move || { loop { if let Some(msg) = ONCE_CELL.get() { tx.send(msg).unwrap(); break; } #[cfg(target_env = "sgx")] crate::thread::yield_now(); } }); } for _ in 0..n_writers { spawn(move || { let _ = ONCE_CELL.set(MSG.to_owned()); }); } for _ in 0..n_readers { let msg = rx.recv().unwrap(); assert_eq!(msg, MSG); } } }