| 1 | use super::poison::once::ExclusiveState; |
| 2 | use crate::cell::UnsafeCell; |
| 3 | use crate::mem::ManuallyDrop; |
| 4 | use crate::ops::{Deref, DerefMut}; |
| 5 | use crate::panic::{RefUnwindSafe, UnwindSafe}; |
| 6 | use crate::sync::Once; |
| 7 | use crate::{fmt, ptr}; |
| 8 | |
| 9 | // We use the state of a Once as discriminant value. Upon creation, the state is |
| 10 | // "incomplete" and `f` contains the initialization closure. In the first call to |
| 11 | // `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state |
| 12 | // is changed to "complete". If it panics, the Once is poisoned, so none of the |
| 13 | // two fields is initialized. |
| 14 | union Data<T, F> { |
| 15 | value: ManuallyDrop<T>, |
| 16 | f: ManuallyDrop<F>, |
| 17 | } |
| 18 | |
| 19 | /// A value which is initialized on the first access. |
| 20 | /// |
| 21 | /// This type is a thread-safe [`LazyCell`], and can be used in statics. |
| 22 | /// Since initialization may be called from multiple threads, any |
| 23 | /// dereferencing call will block the calling thread if another |
| 24 | /// initialization routine is currently running. |
| 25 | /// |
| 26 | /// [`LazyCell`]: crate::cell::LazyCell |
| 27 | /// |
| 28 | /// # Examples |
| 29 | /// |
| 30 | /// Initialize static variables with `LazyLock`. |
| 31 | /// ``` |
| 32 | /// use std::sync::LazyLock; |
| 33 | /// |
| 34 | /// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated. |
| 35 | /// // this is fine, as the OS can deallocate the terminated program faster than we can free memory |
| 36 | /// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional. |
| 37 | /// static DEEP_THOUGHT: LazyLock<String> = LazyLock::new(|| { |
| 38 | /// # mod another_crate { |
| 39 | /// # pub fn great_question() -> String { "42" .to_string() } |
| 40 | /// # } |
| 41 | /// // M3 Ultra takes about 16 million years in --release config |
| 42 | /// another_crate::great_question() |
| 43 | /// }); |
| 44 | /// |
| 45 | /// // The `String` is built, stored in the `LazyLock`, and returned as `&String`. |
| 46 | /// let _ = &*DEEP_THOUGHT; |
| 47 | /// ``` |
| 48 | /// |
| 49 | /// Initialize fields with `LazyLock`. |
| 50 | /// ``` |
| 51 | /// use std::sync::LazyLock; |
| 52 | /// |
| 53 | /// #[derive(Debug)] |
| 54 | /// struct UseCellLock { |
| 55 | /// number: LazyLock<u32>, |
| 56 | /// } |
| 57 | /// fn main() { |
| 58 | /// let lock: LazyLock<u32> = LazyLock::new(|| 0u32); |
| 59 | /// |
| 60 | /// let data = UseCellLock { number: lock }; |
| 61 | /// println!("{}" , *data.number); |
| 62 | /// } |
| 63 | /// ``` |
| 64 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 65 | pub struct LazyLock<T, F = fn() -> T> { |
| 66 | // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available |
| 67 | once: Once, |
| 68 | data: UnsafeCell<Data<T, F>>, |
| 69 | } |
| 70 | |
| 71 | impl<T, F: FnOnce() -> T> LazyLock<T, F> { |
| 72 | /// Creates a new lazy value with the given initializing function. |
| 73 | /// |
| 74 | /// # Examples |
| 75 | /// |
| 76 | /// ``` |
| 77 | /// use std::sync::LazyLock; |
| 78 | /// |
| 79 | /// let hello = "Hello, World!" .to_string(); |
| 80 | /// |
| 81 | /// let lazy = LazyLock::new(|| hello.to_uppercase()); |
| 82 | /// |
| 83 | /// assert_eq!(&*lazy, "HELLO, WORLD!" ); |
| 84 | /// ``` |
| 85 | #[inline ] |
| 86 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 87 | #[rustc_const_stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 88 | pub const fn new(f: F) -> LazyLock<T, F> { |
| 89 | LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) } |
| 90 | } |
| 91 | |
| 92 | /// Creates a new lazy value that is already initialized. |
| 93 | #[inline ] |
| 94 | #[cfg (test)] |
| 95 | pub(crate) fn preinit(value: T) -> LazyLock<T, F> { |
| 96 | let once = Once::new(); |
| 97 | once.call_once(|| {}); |
| 98 | LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) } |
| 99 | } |
| 100 | |
| 101 | /// Consumes this `LazyLock` returning the stored value. |
| 102 | /// |
| 103 | /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. |
| 104 | /// |
| 105 | /// # Examples |
| 106 | /// |
| 107 | /// ``` |
| 108 | /// #![feature(lazy_cell_into_inner)] |
| 109 | /// |
| 110 | /// use std::sync::LazyLock; |
| 111 | /// |
| 112 | /// let hello = "Hello, World!" .to_string(); |
| 113 | /// |
| 114 | /// let lazy = LazyLock::new(|| hello.to_uppercase()); |
| 115 | /// |
| 116 | /// assert_eq!(&*lazy, "HELLO, WORLD!" ); |
| 117 | /// assert_eq!(LazyLock::into_inner(lazy).ok(), Some("HELLO, WORLD!" .to_string())); |
| 118 | /// ``` |
| 119 | #[unstable (feature = "lazy_cell_into_inner" , issue = "125623" )] |
| 120 | pub fn into_inner(mut this: Self) -> Result<T, F> { |
| 121 | let state = this.once.state(); |
| 122 | match state { |
| 123 | ExclusiveState::Poisoned => panic_poisoned(), |
| 124 | state => { |
| 125 | let this = ManuallyDrop::new(this); |
| 126 | let data = unsafe { ptr::read(&this.data) }.into_inner(); |
| 127 | match state { |
| 128 | ExclusiveState::Incomplete => Err(ManuallyDrop::into_inner(unsafe { data.f })), |
| 129 | ExclusiveState::Complete => Ok(ManuallyDrop::into_inner(unsafe { data.value })), |
| 130 | ExclusiveState::Poisoned => unreachable!(), |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | /// Forces the evaluation of this lazy value and returns a mutable reference to |
| 137 | /// the result. |
| 138 | /// |
| 139 | /// # Examples |
| 140 | /// |
| 141 | /// ``` |
| 142 | /// #![feature(lazy_get)] |
| 143 | /// use std::sync::LazyLock; |
| 144 | /// |
| 145 | /// let mut lazy = LazyLock::new(|| 92); |
| 146 | /// |
| 147 | /// let p = LazyLock::force_mut(&mut lazy); |
| 148 | /// assert_eq!(*p, 92); |
| 149 | /// *p = 44; |
| 150 | /// assert_eq!(*lazy, 44); |
| 151 | /// ``` |
| 152 | #[inline ] |
| 153 | #[unstable (feature = "lazy_get" , issue = "129333" )] |
| 154 | pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T { |
| 155 | #[cold ] |
| 156 | /// # Safety |
| 157 | /// May only be called when the state is `Incomplete`. |
| 158 | unsafe fn really_init_mut<T, F: FnOnce() -> T>(this: &mut LazyLock<T, F>) -> &mut T { |
| 159 | struct PoisonOnPanic<'a, T, F>(&'a mut LazyLock<T, F>); |
| 160 | impl<T, F> Drop for PoisonOnPanic<'_, T, F> { |
| 161 | #[inline ] |
| 162 | fn drop(&mut self) { |
| 163 | self.0.once.set_state(ExclusiveState::Poisoned); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | // SAFETY: We always poison if the initializer panics (then we never check the data), |
| 168 | // or set the data on success. |
| 169 | let f = unsafe { ManuallyDrop::take(&mut this.data.get_mut().f) }; |
| 170 | // INVARIANT: Initiated from mutable reference, don't drop because we read it. |
| 171 | let guard = PoisonOnPanic(this); |
| 172 | let data = f(); |
| 173 | guard.0.data.get_mut().value = ManuallyDrop::new(data); |
| 174 | guard.0.once.set_state(ExclusiveState::Complete); |
| 175 | core::mem::forget(guard); |
| 176 | // SAFETY: We put the value there above. |
| 177 | unsafe { &mut this.data.get_mut().value } |
| 178 | } |
| 179 | |
| 180 | let state = this.once.state(); |
| 181 | match state { |
| 182 | ExclusiveState::Poisoned => panic_poisoned(), |
| 183 | // SAFETY: The `Once` states we completed the initialization. |
| 184 | ExclusiveState::Complete => unsafe { &mut this.data.get_mut().value }, |
| 185 | // SAFETY: The state is `Incomplete`. |
| 186 | ExclusiveState::Incomplete => unsafe { really_init_mut(this) }, |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | /// Forces the evaluation of this lazy value and returns a reference to |
| 191 | /// result. This is equivalent to the `Deref` impl, but is explicit. |
| 192 | /// |
| 193 | /// This method will block the calling thread if another initialization |
| 194 | /// routine is currently running. |
| 195 | /// |
| 196 | /// # Examples |
| 197 | /// |
| 198 | /// ``` |
| 199 | /// use std::sync::LazyLock; |
| 200 | /// |
| 201 | /// let lazy = LazyLock::new(|| 92); |
| 202 | /// |
| 203 | /// assert_eq!(LazyLock::force(&lazy), &92); |
| 204 | /// assert_eq!(&*lazy, &92); |
| 205 | /// ``` |
| 206 | #[inline ] |
| 207 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 208 | pub fn force(this: &LazyLock<T, F>) -> &T { |
| 209 | this.once.call_once(|| { |
| 210 | // SAFETY: `call_once` only runs this closure once, ever. |
| 211 | let data = unsafe { &mut *this.data.get() }; |
| 212 | let f = unsafe { ManuallyDrop::take(&mut data.f) }; |
| 213 | let value = f(); |
| 214 | data.value = ManuallyDrop::new(value); |
| 215 | }); |
| 216 | |
| 217 | // SAFETY: |
| 218 | // There are four possible scenarios: |
| 219 | // * the closure was called and initialized `value`. |
| 220 | // * the closure was called and panicked, so this point is never reached. |
| 221 | // * the closure was not called, but a previous call initialized `value`. |
| 222 | // * the closure was not called because the Once is poisoned, so this point |
| 223 | // is never reached. |
| 224 | // So `value` has definitely been initialized and will not be modified again. |
| 225 | unsafe { &*(*this.data.get()).value } |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | impl<T, F> LazyLock<T, F> { |
| 230 | /// Returns a mutable reference to the value if initialized, or `None` if not. |
| 231 | /// |
| 232 | /// # Examples |
| 233 | /// |
| 234 | /// ``` |
| 235 | /// #![feature(lazy_get)] |
| 236 | /// |
| 237 | /// use std::sync::LazyLock; |
| 238 | /// |
| 239 | /// let mut lazy = LazyLock::new(|| 92); |
| 240 | /// |
| 241 | /// assert_eq!(LazyLock::get_mut(&mut lazy), None); |
| 242 | /// let _ = LazyLock::force(&lazy); |
| 243 | /// *LazyLock::get_mut(&mut lazy).unwrap() = 44; |
| 244 | /// assert_eq!(*lazy, 44); |
| 245 | /// ``` |
| 246 | #[inline ] |
| 247 | #[unstable (feature = "lazy_get" , issue = "129333" )] |
| 248 | pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> { |
| 249 | // `state()` does not perform an atomic load, so prefer it over `is_complete()`. |
| 250 | let state = this.once.state(); |
| 251 | match state { |
| 252 | // SAFETY: |
| 253 | // The closure has been run successfully, so `value` has been initialized. |
| 254 | ExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }), |
| 255 | _ => None, |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | /// Returns a reference to the value if initialized, or `None` if not. |
| 260 | /// |
| 261 | /// # Examples |
| 262 | /// |
| 263 | /// ``` |
| 264 | /// #![feature(lazy_get)] |
| 265 | /// |
| 266 | /// use std::sync::LazyLock; |
| 267 | /// |
| 268 | /// let lazy = LazyLock::new(|| 92); |
| 269 | /// |
| 270 | /// assert_eq!(LazyLock::get(&lazy), None); |
| 271 | /// let _ = LazyLock::force(&lazy); |
| 272 | /// assert_eq!(LazyLock::get(&lazy), Some(&92)); |
| 273 | /// ``` |
| 274 | #[inline ] |
| 275 | #[unstable (feature = "lazy_get" , issue = "129333" )] |
| 276 | pub fn get(this: &LazyLock<T, F>) -> Option<&T> { |
| 277 | if this.once.is_completed() { |
| 278 | // SAFETY: |
| 279 | // The closure has been run successfully, so `value` has been initialized |
| 280 | // and will not be modified again. |
| 281 | Some(unsafe { &(*this.data.get()).value }) |
| 282 | } else { |
| 283 | None |
| 284 | } |
| 285 | } |
| 286 | } |
| 287 | |
| 288 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 289 | impl<T, F> Drop for LazyLock<T, F> { |
| 290 | fn drop(&mut self) { |
| 291 | match self.once.state() { |
| 292 | ExclusiveState::Incomplete => unsafe { ManuallyDrop::drop(&mut self.data.get_mut().f) }, |
| 293 | ExclusiveState::Complete => unsafe { |
| 294 | ManuallyDrop::drop(&mut self.data.get_mut().value) |
| 295 | }, |
| 296 | ExclusiveState::Poisoned => {} |
| 297 | } |
| 298 | } |
| 299 | } |
| 300 | |
| 301 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 302 | impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { |
| 303 | type Target = T; |
| 304 | |
| 305 | /// Dereferences the value. |
| 306 | /// |
| 307 | /// This method will block the calling thread if another initialization |
| 308 | /// routine is currently running. |
| 309 | /// |
| 310 | #[inline ] |
| 311 | fn deref(&self) -> &T { |
| 312 | LazyLock::force(self) |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | #[stable (feature = "lazy_deref_mut" , since = "CURRENT_RUSTC_VERSION" )] |
| 317 | impl<T, F: FnOnce() -> T> DerefMut for LazyLock<T, F> { |
| 318 | #[inline ] |
| 319 | fn deref_mut(&mut self) -> &mut T { |
| 320 | LazyLock::force_mut(self) |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 325 | impl<T: Default> Default for LazyLock<T> { |
| 326 | /// Creates a new lazy value using `Default` as the initializing function. |
| 327 | #[inline ] |
| 328 | fn default() -> LazyLock<T> { |
| 329 | LazyLock::new(T::default) |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 334 | impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> { |
| 335 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 336 | let mut d: DebugTuple<'_, '_> = f.debug_tuple(name:"LazyLock" ); |
| 337 | match LazyLock::get(self) { |
| 338 | Some(v: &T) => d.field(v), |
| 339 | None => d.field(&format_args!("<uninit>" )), |
| 340 | }; |
| 341 | d.finish() |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | #[cold ] |
| 346 | #[inline (never)] |
| 347 | fn panic_poisoned() -> ! { |
| 348 | panic!("LazyLock instance has previously been poisoned" ) |
| 349 | } |
| 350 | |
| 351 | // We never create a `&F` from a `&LazyLock<T, F>` so it is fine |
| 352 | // to not impl `Sync` for `F`. |
| 353 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 354 | unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {} |
| 355 | // auto-derived `Send` impl is OK. |
| 356 | |
| 357 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 358 | impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {} |
| 359 | #[stable (feature = "lazy_cell" , since = "1.80.0" )] |
| 360 | impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {} |
| 361 | |