1 use crate::std::cell::UnsafeCell; 2 use crate::std::fmt; 3 use crate::std::marker::PhantomData; 4 use crate::std::mem::MaybeUninit; 5 use crate::std::panic::{RefUnwindSafe, UnwindSafe}; 6 use crate::std::sync::Once; 7 8 /// A synchronization primitive which can be written to only once. 9 /// 10 /// This type is a thread-safe [`OnceCell`], and can be used in statics. 11 /// 12 /// [`OnceCell`]: crate::std::cell::OnceCell 13 /// 14 /// # Examples 15 /// 16 /// ``` 17 /// use std::sync::OnceLock; 18 /// 19 /// static CELL: OnceLock<String> = OnceLock::new(); 20 /// assert!(CELL.get().is_none()); 21 /// 22 /// std::thread::spawn(|| { 23 /// let value: &String = CELL.get_or_init(|| { 24 /// "Hello, World!".to_string() 25 /// }); 26 /// assert_eq!(value, "Hello, World!"); 27 /// }).join().unwrap(); 28 /// 29 /// let value: Option<&String> = CELL.get(); 30 /// assert!(value.is_some()); 31 /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); 32 /// ``` 33 pub struct OnceLock<T> { 34 once: Once, 35 // Whether or not the value is initialized is tracked by `once.is_completed()`. 36 value: UnsafeCell<MaybeUninit<T>>, 37 /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. 38 /// 39 /// ```compile_fail,E0597 40 /// use std::sync::OnceLock; 41 /// 42 /// struct A<'a>(&'a str); 43 /// 44 /// impl<'a> Drop for A<'a> { 45 /// fn drop(&mut self) {} 46 /// } 47 /// 48 /// let cell = OnceLock::new(); 49 /// { 50 /// let s = String::new(); 51 /// let _ = cell.set(A(&s)); 52 /// } 53 /// ``` 54 _marker: PhantomData<T>, 55 } 56 57 impl<T> OnceLock<T> { 58 /// Creates a new empty cell. 59 #[inline] 60 #[must_use] 61 pub const fn new() -> OnceLock<T> { 62 OnceLock { 63 once: Once::new(), 64 value: UnsafeCell::new(MaybeUninit::uninit()), 65 _marker: PhantomData, 66 } 67 } 68 69 /// Gets the reference to the underlying value. 70 /// 71 /// Returns `None` if the cell is empty, or being initialized. This 72 /// method never blocks. 73 #[inline] 74 pub fn get(&self) -> Option<&T> { 75 if self.is_initialized() { 76 // Safe b/c checked is_initialized 77 Some(unsafe { self.get_unchecked() }) 78 } else { 79 None 80 } 81 } 82 83 /// Gets the mutable reference to the underlying value. 84 /// 85 /// Returns `None` if the cell is empty. This method never blocks. 86 #[inline] 87 pub fn get_mut(&mut self) -> Option<&mut T> { 88 if self.is_initialized() { 89 // Safe b/c checked is_initialized and we have a unique access 90 Some(unsafe { self.get_unchecked_mut() }) 91 } else { 92 None 93 } 94 } 95 96 /// Sets the contents of this cell to `value`. 97 /// 98 /// May block if another thread is currently attempting to initialize the cell. The cell is 99 /// guaranteed to contain a value when set returns, though not necessarily the one provided. 100 /// 101 /// Returns `Ok(())` if the cell's value was set by this call. 102 /// 103 /// # Examples 104 /// 105 /// ``` 106 /// use std::sync::OnceLock; 107 /// 108 /// static CELL: OnceLock<i32> = OnceLock::new(); 109 /// 110 /// fn main() { 111 /// assert!(CELL.get().is_none()); 112 /// 113 /// std::thread::spawn(|| { 114 /// assert_eq!(CELL.set(92), Ok(())); 115 /// }).join().unwrap(); 116 /// 117 /// assert_eq!(CELL.set(62), Err(62)); 118 /// assert_eq!(CELL.get(), Some(&92)); 119 /// } 120 /// ``` 121 #[inline] 122 pub fn set(&self, value: T) -> Result<(), T> { 123 let mut value = Some(value); 124 self.get_or_init(|| value.take().unwrap()); 125 match value { 126 None => Ok(()), 127 Some(value) => Err(value), 128 } 129 } 130 131 /// Gets the contents of the cell, initializing it with `f` if the cell 132 /// was empty. 133 /// 134 /// Many threads may call `get_or_init` concurrently with different 135 /// initializing functions, but it is guaranteed that only one function 136 /// will be executed. 137 /// 138 /// # Panics 139 /// 140 /// If `f` panics, the panic is propagated to the caller, and the cell 141 /// remains uninitialized. 142 /// 143 /// It is an error to reentrantly initialize the cell from `f`. The 144 /// exact outcome is unspecified. Current implementation deadlocks, but 145 /// this may be changed to a panic in the future. 146 /// 147 /// # Examples 148 /// 149 /// ``` 150 /// use std::sync::OnceLock; 151 /// 152 /// let cell = OnceLock::new(); 153 /// let value = cell.get_or_init(|| 92); 154 /// assert_eq!(value, &92); 155 /// let value = cell.get_or_init(|| unreachable!()); 156 /// assert_eq!(value, &92); 157 /// ``` 158 #[inline] 159 pub fn get_or_init<F>(&self, f: F) -> &T 160 where 161 F: FnOnce() -> T, 162 { 163 match self.get_or_try_init(|| Ok::<T, !>(f())) { 164 Ok(val) => val, 165 Err(_) => todo!(), 166 } 167 } 168 169 /// Gets the contents of the cell, initializing it with `f` if 170 /// the cell was empty. If the cell was empty and `f` failed, an 171 /// error is returned. 172 /// 173 /// # Panics 174 /// 175 /// If `f` panics, the panic is propagated to the caller, and 176 /// the cell remains uninitialized. 177 /// 178 /// It is an error to reentrantly initialize the cell from `f`. 179 /// The exact outcome is unspecified. Current implementation 180 /// deadlocks, but this may be changed to a panic in the future. 181 /// 182 /// # Examples 183 /// 184 /// ``` 185 /// #![feature(once_cell_try)] 186 /// 187 /// use std::sync::OnceLock; 188 /// 189 /// let cell = OnceLock::new(); 190 /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); 191 /// assert!(cell.get().is_none()); 192 /// let value = cell.get_or_try_init(|| -> Result<i32, ()> { 193 /// Ok(92) 194 /// }); 195 /// assert_eq!(value, Ok(&92)); 196 /// assert_eq!(cell.get(), Some(&92)) 197 /// ``` 198 #[inline] 199 pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> 200 where 201 F: FnOnce() -> Result<T, E>, 202 { 203 // Fast path check 204 // NOTE: We need to perform an acquire on the state in this method 205 // in order to correctly synchronize `LazyLock::force`. This is 206 // currently done by calling `self.get()`, which in turn calls 207 // `self.is_initialized()`, which in turn performs the acquire. 208 if let Some(value) = self.get() { 209 return Ok(value); 210 } 211 self.initialize(f)?; 212 213 debug_assert!(self.is_initialized()); 214 215 // SAFETY: The inner value has been initialized 216 Ok(unsafe { self.get_unchecked() }) 217 } 218 219 /// Consumes the `OnceLock`, returning the wrapped value. Returns 220 /// `None` if the cell was empty. 221 /// 222 /// # Examples 223 /// 224 /// ``` 225 /// use std::sync::OnceLock; 226 /// 227 /// let cell: OnceLock<String> = OnceLock::new(); 228 /// assert_eq!(cell.into_inner(), None); 229 /// 230 /// let cell = OnceLock::new(); 231 /// cell.set("hello".to_string()).unwrap(); 232 /// assert_eq!(cell.into_inner(), Some("hello".to_string())); 233 /// ``` 234 #[inline] 235 pub fn into_inner(mut self) -> Option<T> { 236 self.take() 237 } 238 239 /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state. 240 /// 241 /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized. 242 /// 243 /// Safety is guaranteed by requiring a mutable reference. 244 /// 245 /// # Examples 246 /// 247 /// ``` 248 /// use std::sync::OnceLock; 249 /// 250 /// let mut cell: OnceLock<String> = OnceLock::new(); 251 /// assert_eq!(cell.take(), None); 252 /// 253 /// let mut cell = OnceLock::new(); 254 /// cell.set("hello".to_string()).unwrap(); 255 /// assert_eq!(cell.take(), Some("hello".to_string())); 256 /// assert_eq!(cell.get(), None); 257 /// ``` 258 #[inline] 259 pub fn take(&mut self) -> Option<T> { 260 if self.is_initialized() { 261 self.once = Once::new(); 262 // SAFETY: `self.value` is initialized and contains a valid `T`. 263 // `self.once` is reset, so `is_initialized()` will be false again 264 // which prevents the value from being read twice. 265 unsafe { Some((&mut *self.value.get()).assume_init_read()) } 266 } else { 267 None 268 } 269 } 270 271 #[inline] 272 fn is_initialized(&self) -> bool { 273 self.once.is_completed() 274 } 275 276 #[cold] 277 fn initialize<F, E>(&self, f: F) -> Result<(), E> 278 where 279 F: FnOnce() -> Result<T, E>, 280 { 281 let mut res: Result<(), E> = Ok(()); 282 let slot = &self.value; 283 284 // Ignore poisoning from other threads 285 // If another thread panics, then we'll be able to run our closure 286 self.once.call_once_force(|p| { 287 match f() { 288 Ok(value) => { 289 unsafe { (&mut *slot.get()).write(value) }; 290 } 291 Err(e) => { 292 res = Err(e); 293 294 // Treat the underlying `Once` as poisoned since we 295 // failed to initialize our value. Calls 296 p.poison(); 297 } 298 } 299 }); 300 res 301 } 302 303 /// # Safety 304 /// 305 /// The value must be initialized 306 #[inline] 307 unsafe fn get_unchecked(&self) -> &T { 308 debug_assert!(self.is_initialized()); 309 (&*self.value.get()).assume_init_ref() 310 } 311 312 /// # Safety 313 /// 314 /// The value must be initialized 315 #[inline] 316 unsafe fn get_unchecked_mut(&mut self) -> &mut T { 317 debug_assert!(self.is_initialized()); 318 (&mut *self.value.get()).assume_init_mut() 319 } 320 } 321 322 // Why do we need `T: Send`? 323 // Thread A creates a `OnceLock` and shares it with 324 // scoped thread B, which fills the cell, which is 325 // then destroyed by A. That is, destructor observes 326 // a sent value. 327 unsafe impl<T: Sync + Send> Sync for OnceLock<T> {} 328 unsafe impl<T: Send> Send for OnceLock<T> {} 329 330 impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {} 331 impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {} 332 333 impl<T> Default for OnceLock<T> { 334 /// Creates a new empty cell. 335 /// 336 /// # Example 337 /// 338 /// ``` 339 /// use std::sync::OnceLock; 340 /// 341 /// fn main() { 342 /// assert_eq!(OnceLock::<()>::new(), OnceLock::default()); 343 /// } 344 /// ``` 345 #[inline] 346 fn default() -> OnceLock<T> { 347 OnceLock::new() 348 } 349 } 350 351 impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { 352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 353 let mut d = f.debug_tuple("OnceLock"); 354 match self.get() { 355 Some(v) => d.field(v), 356 None => d.field(&format_args!("<uninit>")), 357 }; 358 d.finish() 359 } 360 } 361 362 impl<T: Clone> Clone for OnceLock<T> { 363 #[inline] 364 fn clone(&self) -> OnceLock<T> { 365 let cell = Self::new(); 366 if let Some(value) = self.get() { 367 match cell.set(value.clone()) { 368 Ok(()) => (), 369 Err(_) => unreachable!(), 370 } 371 } 372 cell 373 } 374 } 375 376 impl<T> From<T> for OnceLock<T> { 377 /// Create a new cell with its contents set to `value`. 378 /// 379 /// # Example 380 /// 381 /// ``` 382 /// use std::sync::OnceLock; 383 /// 384 /// # fn main() -> Result<(), i32> { 385 /// let a = OnceLock::from(3); 386 /// let b = OnceLock::new(); 387 /// b.set(3)?; 388 /// assert_eq!(a, b); 389 /// Ok(()) 390 /// # } 391 /// ``` 392 #[inline] 393 fn from(value: T) -> Self { 394 let cell = Self::new(); 395 match cell.set(value) { 396 Ok(()) => cell, 397 Err(_) => unreachable!(), 398 } 399 } 400 } 401 402 impl<T: PartialEq> PartialEq for OnceLock<T> { 403 #[inline] 404 fn eq(&self, other: &OnceLock<T>) -> bool { 405 self.get() == other.get() 406 } 407 } 408 409 impl<T: Eq> Eq for OnceLock<T> {} 410 411 unsafe impl<#[may_dangle] T> Drop for OnceLock<T> { 412 #[inline] 413 fn drop(&mut self) { 414 if self.is_initialized() { 415 // SAFETY: The cell is initialized and being dropped, so it can't 416 // be accessed again. We also don't touch the `T` other than 417 // dropping it, which validates our usage of #[may_dangle]. 418 unsafe { (&mut *self.value.get()).assume_init_drop() }; 419 } 420 } 421 } 422 423 #[cfg(test)] 424 mod tests; 425