1 #[cfg(feature = "std")] 2 pub(crate) use once_cell::sync::Lazy; 3 4 #[cfg(not(feature = "std"))] 5 pub(crate) use self::spin::Lazy; 6 7 #[cfg(not(feature = "std"))] 8 mod spin { 9 //! This is the `once_cell::sync::Lazy` type, but modified to use our 10 //! `spin::Once` type rather than `OnceCell`. This is used to replace 11 //! `once_cell::sync::Lazy` on `no-std` builds. 12 use crate::spin::Once; 13 use core::{cell::Cell, fmt, ops::Deref}; 14 15 /// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once` 16 /// rather than `OnceCell`. 17 /// 18 /// This is used when the standard library is disabled. 19 pub(crate) struct Lazy<T, F = fn() -> T> { 20 cell: Once<T>, 21 init: Cell<Option<F>>, 22 } 23 24 impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 26 f.debug_struct("Lazy") 27 .field("cell", &self.cell) 28 .field("init", &"..") 29 .finish() 30 } 31 } 32 33 // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl 34 // `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is 35 // properly synchronized, so it only happens once so it also does not 36 // contribute to this impl. 37 unsafe impl<T, F: Send> Sync for Lazy<T, F> where Once<T>: Sync {} 38 // auto-derived `Send` impl is OK. 39 40 impl<T, F> Lazy<T, F> { 41 /// Creates a new lazy value with the given initializing function. new(init: F) -> Lazy<T, F>42 pub(crate) const fn new(init: F) -> Lazy<T, F> { 43 Lazy { 44 cell: Once::new(), 45 init: Cell::new(Some(init)), 46 } 47 } 48 } 49 50 impl<T, F: FnOnce() -> T> Lazy<T, F> { 51 /// Forces the evaluation of this lazy value and returns a reference to 52 /// the result. 53 /// 54 /// This is equivalent to the `Deref` impl, but is explicit. force(this: &Lazy<T, F>) -> &T55 pub(crate) fn force(this: &Lazy<T, F>) -> &T { 56 this.cell.call_once(|| match this.init.take() { 57 Some(f) => f(), 58 None => panic!("Lazy instance has previously been poisoned"), 59 }) 60 } 61 } 62 63 impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 64 type Target = T; deref(&self) -> &T65 fn deref(&self) -> &T { 66 Lazy::force(self) 67 } 68 } 69 70 impl<T: Default> Default for Lazy<T> { 71 /// Creates a new lazy value using `Default` as the initializing function. default() -> Lazy<T>72 fn default() -> Lazy<T> { 73 Lazy::new(T::default) 74 } 75 } 76 } 77