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