use crate::cell::Cell; use crate::fmt; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::OnceLock; /// A value which is initialized on the first access. /// /// This type is a thread-safe [`LazyCell`], and can be used in statics. /// /// [`LazyCell`]: crate::cell::LazyCell /// /// # Examples /// /// ``` /// #![feature(once_cell)] /// /// use std::collections::HashMap; /// /// use std::sync::LazyLock; /// /// static HASHMAP: LazyLock> = LazyLock::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 LazyLock T> { cell: OnceLock, init: Cell>, } impl T> LazyLock { /// Creates a new lazy value with the given initializing /// function. #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(f: F) -> LazyLock { LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) } } /// 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::sync::LazyLock; /// /// let lazy = LazyLock::new(|| 92); /// /// assert_eq!(LazyLock::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyLock) -> &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 LazyLock { type Target = T; #[inline] fn deref(&self) -> &T { LazyLock::force(self) } } #[unstable(feature = "once_cell", issue = "74465")] impl Default for LazyLock { /// Creates a new lazy value using `Default` as the initializing function. #[inline] fn default() -> LazyLock { LazyLock::new(T::default) } } #[unstable(feature = "once_cell", issue = "74465")] impl fmt::Debug for LazyLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive() } } // We never create a `&F` from a `&LazyLock` 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 LazyLock where OnceLock: Sync {} // auto-derived `Send` impl is OK. #[unstable(feature = "once_cell", issue = "74465")] impl RefUnwindSafe for LazyLock where OnceLock: RefUnwindSafe {} #[unstable(feature = "once_cell", issue = "74465")] impl UnwindSafe for LazyLock where OnceLock: UnwindSafe {} #[cfg(test)] mod tests;