1 //! Synchronization primitives for lazy evaluation. 2 //! 3 //! Implementation adapted from the `SyncLazy` type of the standard library. See: 4 //! <https://doc.rust-lang.org/std/lazy/struct.SyncLazy.html> 5 6 use crate::{once::Once, RelaxStrategy, Spin}; 7 use core::{cell::Cell, fmt, ops::Deref}; 8 9 /// A value which is initialized on the first access. 10 /// 11 /// This type is a thread-safe `Lazy`, and can be used in statics. 12 /// 13 /// # Examples 14 /// 15 /// ``` 16 /// use std::collections::HashMap; 17 /// use spin::Lazy; 18 /// 19 /// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::new(|| { 20 /// println!("initializing"); 21 /// let mut m = HashMap::new(); 22 /// m.insert(13, "Spica".to_string()); 23 /// m.insert(74, "Hoyten".to_string()); 24 /// m 25 /// }); 26 /// 27 /// fn main() { 28 /// println!("ready"); 29 /// std::thread::spawn(|| { 30 /// println!("{:?}", HASHMAP.get(&13)); 31 /// }).join().unwrap(); 32 /// println!("{:?}", HASHMAP.get(&74)); 33 /// 34 /// // Prints: 35 /// // ready 36 /// // initializing 37 /// // Some("Spica") 38 /// // Some("Hoyten") 39 /// } 40 /// ``` 41 pub struct Lazy<T, F = fn() -> T, R = Spin> { 42 cell: Once<T, R>, 43 init: Cell<Option<F>>, 44 } 45 46 impl<T: fmt::Debug, F, R> fmt::Debug for Lazy<T, F, R> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 48 f.debug_struct("Lazy") 49 .field("cell", &self.cell) 50 .field("init", &"..") 51 .finish() 52 } 53 } 54 55 // We never create a `&F` from a `&Lazy<T, F>` so it is fine 56 // to not impl `Sync` for `F` 57 // we do create a `&mut Option<F>` in `force`, but this is 58 // properly synchronized, so it only happens once 59 // so it also does not contribute to this impl. 60 unsafe impl<T, F: Send> Sync for Lazy<T, F> where Once<T>: Sync {} 61 // auto-derived `Send` impl is OK. 62 63 impl<T, F, R> Lazy<T, F, R> { 64 /// Creates a new lazy value with the given initializing 65 /// function. new(f: F) -> Self66 pub const fn new(f: F) -> Self { 67 Self { 68 cell: Once::new(), 69 init: Cell::new(Some(f)), 70 } 71 } 72 /// Retrieves a mutable pointer to the inner data. 73 /// 74 /// This is especially useful when interfacing with low level code or FFI where the caller 75 /// explicitly knows that it has exclusive access to the inner data. Note that reading from 76 /// this pointer is UB until initialized or directly written to. as_mut_ptr(&self) -> *mut T77 pub fn as_mut_ptr(&self) -> *mut T { 78 self.cell.as_mut_ptr() 79 } 80 } 81 82 impl<T, F: FnOnce() -> T, R: RelaxStrategy> Lazy<T, F, R> { 83 /// Forces the evaluation of this lazy value and 84 /// returns a reference to result. This is equivalent 85 /// to the `Deref` impl, but is explicit. 86 /// 87 /// # Examples 88 /// 89 /// ``` 90 /// use spin::Lazy; 91 /// 92 /// let lazy = Lazy::new(|| 92); 93 /// 94 /// assert_eq!(Lazy::force(&lazy), &92); 95 /// assert_eq!(&*lazy, &92); 96 /// ``` force(this: &Self) -> &T97 pub fn force(this: &Self) -> &T { 98 this.cell.call_once(|| match this.init.take() { 99 Some(f) => f(), 100 None => panic!("Lazy instance has previously been poisoned"), 101 }) 102 } 103 } 104 105 impl<T, F: FnOnce() -> T, R: RelaxStrategy> Deref for Lazy<T, F, R> { 106 type Target = T; 107 deref(&self) -> &T108 fn deref(&self) -> &T { 109 Self::force(self) 110 } 111 } 112 113 impl<T: Default, R> Default for Lazy<T, fn() -> T, R> { 114 /// Creates a new lazy value using `Default` as the initializing function. default() -> Self115 fn default() -> Self { 116 Self::new(T::default) 117 } 118 } 119