]> git.proxmox.com Git - rustc.git/blame - library/std/src/lazy.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / library / std / src / lazy.rs
CommitLineData
3dfed10e
XL
1//! Lazy values and one-time initialization of static data.
2
1b1a35ee
XL
3#[cfg(test)]
4mod tests;
5
3dfed10e
XL
6use 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")]
18pub 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")]
46pub 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")]
78unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
79#[unstable(feature = "once_cell", issue = "74465")]
80unsafe impl<T: Send> Send for SyncOnceCell<T> {}
81
82#[unstable(feature = "once_cell", issue = "74465")]
83impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SyncOnceCell<T> {}
84#[unstable(feature = "once_cell", issue = "74465")]
85impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
86
87#[unstable(feature = "once_cell", issue = "74465")]
88impl<T> Default for SyncOnceCell<T> {
89 fn default() -> SyncOnceCell<T> {
90 SyncOnceCell::new()
91 }
92}
93
94#[unstable(feature = "once_cell", issue = "74465")]
95impl<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")]
105impl<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")]
119impl<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")]
130impl<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")]
137impl<T: Eq> Eq for SyncOnceCell<T> {}
138
139impl<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
401unsafe 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")]
448pub struct SyncLazy<T, F = fn() -> T> {
449 cell: SyncOnceCell<T>,
450 init: Cell<Option<F>>,
451}
452
453#[unstable(feature = "once_cell", issue = "74465")]
454impl<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")]
466unsafe 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")]
470impl<T, F: UnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
471#[unstable(feature = "once_cell", issue = "74465")]
472impl<T, F: UnwindSafe> UnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: UnwindSafe {}
473
474impl<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
483impl<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")]
510impl<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")]
518impl<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}