async_lock/once_cell.rs
1use core::cell::UnsafeCell;
2use core::convert::Infallible;
3use core::fmt;
4use core::future::Future;
5use core::mem::{forget, MaybeUninit};
6use core::ptr;
7
8use crate::sync::atomic::{AtomicUsize, Ordering};
9
10#[cfg(not(loom))]
11use crate::sync::WithMut;
12
13use event_listener::Event;
14use event_listener_strategy::{NonBlocking, Strategy};
15
16#[cfg(all(feature = "std", not(target_family = "wasm")))]
17use event_listener::Listener;
18
19/// The current state of the `OnceCell`.
20#[derive(Copy, Clone, PartialEq, Eq)]
21#[repr(usize)]
22enum State {
23 /// The `OnceCell` is uninitialized.
24 Uninitialized = 0,
25 /// The `OnceCell` is being initialized.
26 Initializing = 1,
27 /// The `OnceCell` is initialized.
28 Initialized = 2,
29}
30
31impl From<usize> for State {
32 fn from(val: usize) -> Self {
33 match val {
34 0 => State::Uninitialized,
35 1 => State::Initializing,
36 2 => State::Initialized,
37 _ => unreachable!("Invalid state"),
38 }
39 }
40}
41
42impl From<State> for usize {
43 fn from(val: State) -> Self {
44 val as usize
45 }
46}
47
48/// A memory location that can be written to at most once.
49///
50/// A `OnceCell` can be used to store a single value, and only once. However,
51/// once the value is stored, it can be accessed directly through a reference
52/// instead of needing an RAII guard like `Mutex` or `RwLock`.
53///
54/// # Examples
55///
56/// This structure is useful for a variety of patterns, most notably for one-time
57/// initialization.
58///
59/// ```rust
60/// use async_lock::OnceCell;
61///
62/// # struct Foobar;
63///
64/// async fn very_expensive_initialization() -> Foobar {
65/// // Imagine this is very expensive to initialize,
66/// // for instance, it requires a network request or
67/// // a database call.
68/// # Foobar
69/// }
70///
71/// struct LazyFoobar {
72/// inner: OnceCell<Foobar>,
73/// }
74///
75/// impl LazyFoobar {
76/// fn new() -> Self {
77/// Self {
78/// inner: OnceCell::new(),
79/// }
80/// }
81///
82/// async fn load(&self) -> &Foobar {
83/// self.inner.get_or_init(|| async {
84/// very_expensive_initialization().await
85/// }).await
86/// }
87/// }
88/// ```
89pub struct OnceCell<T> {
90 /// Listeners waiting for a chance to initialize the cell.
91 ///
92 /// These are the users of get_or_init() and similar functions.
93 active_initializers: Event,
94
95 /// Listeners waiting for the cell to be initialized.
96 ///
97 /// These are the users of wait().
98 passive_waiters: Event,
99
100 /// State associated with the cell.
101 state: AtomicUsize,
102
103 /// The value of the cell.
104 value: UnsafeCell<MaybeUninit<T>>,
105}
106
107unsafe impl<T: Send> Send for OnceCell<T> {}
108unsafe impl<T: Send + Sync> Sync for OnceCell<T> {}
109
110impl<T> OnceCell<T> {
111 const_fn! {
112 const_if: #[cfg(not(loom))];
113 /// Create a new, uninitialized `OnceCell`.
114 ///
115 /// # Example
116 ///
117 /// ```rust
118 /// use async_lock::OnceCell;
119 ///
120 /// let cell = OnceCell::new();
121 /// # let _: Option<&u32> = cell.get();
122 /// ```
123 pub const fn new() -> Self {
124 Self {
125 active_initializers: Event::new(),
126 passive_waiters: Event::new(),
127 state: AtomicUsize::new(State::Uninitialized as _),
128 value: UnsafeCell::new(MaybeUninit::uninit()),
129 }
130 }
131 }
132
133 /// Tell whether or not the cell is initialized.
134 ///
135 /// This may not always be accurate. For instance, it is possible for
136 /// another thread to initialize the cell between the time when this
137 /// function is called and the time when the result is actually used.
138 ///
139 /// # Example
140 ///
141 /// ```rust
142 /// use async_lock::OnceCell;
143 ///
144 /// # futures_lite::future::block_on(async {
145 /// let cell = OnceCell::new();
146 /// assert!(!cell.is_initialized());
147 /// cell.set(1).await;
148 /// assert!(cell.is_initialized());
149 /// # });
150 /// ```
151 pub fn is_initialized(&self) -> bool {
152 State::from(self.state.load(Ordering::Acquire)) == State::Initialized
153 }
154
155 /// Get a reference to the inner value, or `None` if the value
156 /// is not yet initialized.
157 ///
158 /// # Example
159 ///
160 /// ```rust
161 /// use async_lock::OnceCell;
162 ///
163 /// # futures_lite::future::block_on(async {
164 /// let cell = OnceCell::new();
165 /// assert!(cell.get().is_none());
166 /// cell.set(1).await;
167 /// assert_eq!(cell.get(), Some(&1));
168 /// # });
169 /// ```
170 pub fn get(&self) -> Option<&T> {
171 if self.is_initialized() {
172 // SAFETY: We know that the value is initialized, so it is safe to
173 // read it.
174 Some(unsafe { self.get_unchecked() })
175 } else {
176 None
177 }
178 }
179
180 /// Get a mutable reference to the inner value, or `None` if the value
181 /// is not yet initialized.
182 ///
183 /// This function is useful for initializing the value inside the cell
184 /// when we still have a mutable reference to the cell.
185 ///
186 /// # Example
187 ///
188 /// ```rust
189 /// use async_lock::OnceCell;
190 ///
191 /// # futures_lite::future::block_on(async {
192 /// let mut cell = OnceCell::new();
193 /// assert!(cell.get_mut().is_none());
194 /// cell.set(1).await;
195 /// assert_eq!(cell.get_mut(), Some(&mut 1));
196 /// *cell.get_mut().unwrap() = 2;
197 /// assert_eq!(cell.get(), Some(&2));
198 /// # });
199 /// ```
200 pub fn get_mut(&mut self) -> Option<&mut T> {
201 self.state.with_mut(|state| {
202 if State::from(*state) == State::Initialized {
203 // SAFETY: We know that the value is initialized, so it is safe to
204 // read it.
205 Some(unsafe { &mut *self.value.get().cast() })
206 } else {
207 None
208 }
209 })
210 }
211
212 /// Take the value out of this `OnceCell`, moving it back to the uninitialized
213 /// state.
214 ///
215 /// # Example
216 ///
217 /// ```rust
218 /// use async_lock::OnceCell;
219 ///
220 /// # futures_lite::future::block_on(async {
221 /// let mut cell = OnceCell::new();
222 /// cell.set(1).await;
223 /// assert_eq!(cell.take(), Some(1));
224 /// assert!(!cell.is_initialized());
225 /// # });
226 /// ```
227 pub fn take(&mut self) -> Option<T> {
228 self.state.with_mut(|state| {
229 if State::from(*state) == State::Initialized {
230 // SAFETY: We know that the value is initialized, so it is safe to
231 // read it.
232 let value = unsafe { ptr::read(self.value.get().cast()) };
233 *state = State::Uninitialized.into();
234 Some(value)
235 } else {
236 None
237 }
238 })
239 }
240
241 /// Convert this `OnceCell` into the inner value, if it is initialized.
242 ///
243 /// # Example
244 ///
245 /// ```rust
246 /// use async_lock::OnceCell;
247 ///
248 /// # futures_lite::future::block_on(async {
249 /// let cell = OnceCell::new();
250 /// cell.set(1).await;
251 /// assert_eq!(cell.into_inner(), Some(1));
252 /// # });
253 /// ```
254 pub fn into_inner(mut self) -> Option<T> {
255 self.take()
256 }
257
258 /// Wait for the cell to be initialized, and then return a reference to the
259 /// inner value.
260 ///
261 /// # Example
262 ///
263 #[cfg_attr(not(target_family = "wasm"), doc = "```rust")]
264 #[cfg_attr(target_family = "wasm", doc = "```ignore")]
265 /// use async_lock::OnceCell;
266 /// use std::sync::Arc;
267 /// use std::time::Duration;
268 /// use std::thread::{sleep, spawn};
269 ///
270 /// let cell = Arc::new(OnceCell::new());
271 /// let cell2 = cell.clone();
272 ///
273 /// spawn(move || {
274 /// sleep(Duration::from_millis(5));
275 /// cell2.set_blocking(1);
276 /// });
277 ///
278 /// # futures_lite::future::block_on(async {
279 /// assert_eq!(cell.wait().await, &1);
280 /// # });
281 /// ```
282 pub async fn wait(&self) -> &T {
283 // Fast path: see if the value is already initialized.
284 if let Some(value) = self.get() {
285 return value;
286 }
287
288 // Slow path: wait for the value to be initialized.
289 event_listener::listener!(self.passive_waiters => listener);
290
291 // Try again.
292 if let Some(value) = self.get() {
293 return value;
294 }
295
296 listener.await;
297 debug_assert!(self.is_initialized());
298
299 // SAFETY: We know that the value is initialized, so it is safe to
300 // read it.
301 unsafe { self.get_unchecked() }
302 }
303
304 /// Wait for the cell to be initialized, and then return a reference to the
305 /// inner value.
306 ///
307 /// # Blocking
308 ///
309 /// In contrast to the `wait` method, this method blocks the current thread of
310 /// execution instead of awaiting.
311 ///
312 /// This method should not be used in an asynchronous context. It is intended
313 /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts.
314 /// Calling this method in an asynchronous context may result in deadlocks.
315 ///
316 /// # Example
317 ///
318 /// ```rust
319 /// use async_lock::OnceCell;
320 /// use std::sync::Arc;
321 /// use std::time::Duration;
322 /// use std::thread::{sleep, spawn};
323 ///
324 /// let cell = Arc::new(OnceCell::new());
325 /// let cell2 = cell.clone();
326 ///
327 /// spawn(move || {
328 /// sleep(Duration::from_millis(5));
329 /// cell2.set_blocking(1);
330 /// });
331 ///
332 /// assert_eq!(cell.wait_blocking(), &1);
333 /// ```
334 #[cfg(all(feature = "std", not(target_family = "wasm")))]
335 pub fn wait_blocking(&self) -> &T {
336 // Fast path: see if the value is already initialized.
337 if let Some(value) = self.get() {
338 return value;
339 }
340
341 // Slow path: wait for the value to be initialized.
342 event_listener::listener!(self.passive_waiters => listener);
343
344 // Try again.
345 if let Some(value) = self.get() {
346 return value;
347 }
348
349 listener.wait();
350 debug_assert!(self.is_initialized());
351
352 // SAFETY: We know that the value is initialized, so it is safe to
353 // read it.
354 unsafe { self.get_unchecked() }
355 }
356
357 /// Either get the value or initialize it with the given closure.
358 ///
359 /// The cell will not be initialized if the closure returns an error.
360 ///
361 /// # Example
362 ///
363 /// ```rust
364 /// use async_lock::OnceCell;
365 /// #
366 /// # // Prevent explicit value errors.
367 /// # fn _explicit(_: &Result<&i32, ()>) {}
368 ///
369 /// # futures_lite::future::block_on(async {
370 /// let cell = OnceCell::new();
371 ///
372 /// let result = cell.get_or_try_init(|| async { Err(()) }).await;
373 /// assert!(result.is_err());
374 ///
375 /// let result = cell.get_or_try_init(|| async { Ok(1) }).await;
376 /// # _explicit(&result);
377 /// assert_eq!(result.unwrap(), &1);
378 ///
379 /// let result = cell.get_or_try_init(|| async { Err(()) }).await;
380 ///
381 /// assert_eq!(result.unwrap(), &1);
382 /// # });
383 /// ```
384 pub async fn get_or_try_init<E, Fut: Future<Output = Result<T, E>>>(
385 &self,
386 closure: impl FnOnce() -> Fut,
387 ) -> Result<&T, E> {
388 // Fast path: see if the value is already initialized.
389 if let Some(value) = self.get() {
390 return Ok(value);
391 }
392
393 // Slow path: initialize the value.
394 self.initialize_or_wait(closure, &mut NonBlocking::default())
395 .await?;
396 debug_assert!(self.is_initialized());
397
398 // SAFETY: We know that the value is initialized, so it is safe to
399 // read it.
400 Ok(unsafe { self.get_unchecked() })
401 }
402
403 /// Either get the value or initialize it with the given closure.
404 ///
405 /// The cell will not be initialized if the closure returns an error.
406 ///
407 /// # Blocking
408 ///
409 /// In contrast to the `get_or_try_init` method, this method blocks the current thread of
410 /// execution instead of awaiting.
411 ///
412 /// This method should not be used in an asynchronous context. It is intended
413 /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts.
414 /// Calling this method in an asynchronous context may result in deadlocks.
415 ///
416 /// # Example
417 ///
418 /// ```rust
419 /// use async_lock::OnceCell;
420 /// #
421 /// # // Prevent explicit type errors.
422 /// # fn _explicit(_: &Result<&i32, ()>) {}
423 ///
424 /// let cell = OnceCell::new();
425 ///
426 /// let result = cell.get_or_try_init_blocking(|| Err(()));
427 /// assert!(result.is_err());
428 ///
429 /// let result = cell.get_or_try_init_blocking(|| Ok(1));
430 /// # _explicit(&result);
431 /// assert_eq!(result.unwrap(), &1);
432 ///
433 /// let result = cell.get_or_try_init_blocking(|| Err(()));
434 ///
435 /// assert_eq!(result.unwrap(), &1);
436 /// ```
437 #[cfg(all(feature = "std", not(target_family = "wasm")))]
438 pub fn get_or_try_init_blocking<E>(
439 &self,
440 closure: impl FnOnce() -> Result<T, E>,
441 ) -> Result<&T, E> {
442 // Fast path: see if the value is already initialized.
443 if let Some(value) = self.get() {
444 return Ok(value);
445 }
446
447 // Slow path: initialize the value.
448 // The futures provided should never block, so we can use `now_or_never`.
449 now_or_never(self.initialize_or_wait(
450 move || core::future::ready(closure()),
451 &mut event_listener_strategy::Blocking::default(),
452 ))?;
453 debug_assert!(self.is_initialized());
454
455 // SAFETY: We know that the value is initialized, so it is safe to
456 // read it.
457 Ok(unsafe { self.get_unchecked() })
458 }
459
460 /// Either get the value or initialize it with the given closure.
461 ///
462 /// Many tasks may call this function, but the value will only be set once
463 /// and only one closure will be invoked.
464 ///
465 /// # Example
466 ///
467 /// ```rust
468 /// use async_lock::OnceCell;
469 ///
470 /// # futures_lite::future::block_on(async {
471 /// let cell = OnceCell::new();
472 /// assert_eq!(cell.get_or_init(|| async { 1 }).await, &1);
473 /// assert_eq!(cell.get_or_init(|| async { 2 }).await, &1);
474 /// # });
475 /// ```
476 pub async fn get_or_init<Fut: Future<Output = T>>(&self, closure: impl FnOnce() -> Fut) -> &T {
477 // false positive: https://github.com/rust-lang/rust/issues/129352
478 #[allow(unreachable_patterns)]
479 match self
480 .get_or_try_init(move || async move {
481 let result: Result<T, Infallible> = Ok(closure().await);
482 result
483 })
484 .await
485 {
486 Ok(value) => value,
487 Err(infallible) => match infallible {},
488 }
489 }
490
491 /// Either get the value or initialize it with the given closure.
492 ///
493 /// Many tasks may call this function, but the value will only be set once
494 /// and only one closure will be invoked.
495 ///
496 /// # Blocking
497 ///
498 /// In contrast to the `get_or_init` method, this method blocks the current thread of
499 /// execution instead of awaiting.
500 ///
501 /// This method should not be used in an asynchronous context. It is intended
502 /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts.
503 /// Calling this method in an asynchronous context may result in deadlocks.
504 ///
505 /// # Example
506 ///
507 /// ```rust
508 /// use async_lock::OnceCell;
509 ///
510 /// let cell = OnceCell::new();
511 /// assert_eq!(cell.get_or_init_blocking(|| 1), &1);
512 /// assert_eq!(cell.get_or_init_blocking(|| 2), &1);
513 /// ```
514 #[cfg(all(feature = "std", not(target_family = "wasm")))]
515 pub fn get_or_init_blocking(&self, closure: impl FnOnce() -> T + Unpin) -> &T {
516 let result = self.get_or_try_init_blocking(move || {
517 let result: Result<T, Infallible> = Ok(closure());
518 result
519 });
520
521 // false positive: https://github.com/rust-lang/rust/issues/129352
522 #[allow(unreachable_patterns)]
523 match result {
524 Ok(value) => value,
525 Err(infallible) => match infallible {},
526 }
527 }
528
529 /// Try to set the value of the cell.
530 ///
531 /// If the cell is already initialized, this method returns the original
532 /// value back.
533 ///
534 /// # Example
535 ///
536 /// ```rust
537 /// use async_lock::OnceCell;
538 ///
539 /// # futures_lite::future::block_on(async {
540 /// let cell = OnceCell::new();
541 ///
542 /// assert_eq!(cell.set(1).await, Ok(&1));
543 /// assert_eq!(cell.get(), Some(&1));
544 /// assert_eq!(cell.set(2).await, Err(2));
545 /// # });
546 /// ```
547 pub async fn set(&self, value: T) -> Result<&T, T> {
548 let mut value = Some(value);
549 self.get_or_init(|| async { value.take().unwrap() }).await;
550
551 match value {
552 Some(value) => Err(value),
553 None => {
554 // SAFETY: value was taken, so we are initialized
555 Ok(unsafe { self.get_unchecked() })
556 }
557 }
558 }
559
560 /// Try to set the value of the cell, without blocking.
561 ///
562 /// If the cell is already initialised *or* the is currently in the process of being
563 /// initialised, this method returns the original value back.
564 ///
565 /// Unlike [`OnceCell::set`] and [`OnceCell::set_blocking`], this function is neither
566 /// blocking nor async.
567 pub fn try_set(&self, value: T) -> Result<(), T> {
568 if self
569 .state
570 .compare_exchange(
571 State::Uninitialized.into(),
572 State::Initializing.into(),
573 Ordering::AcqRel,
574 Ordering::Acquire,
575 )
576 .is_ok()
577 {
578 // Write the value into the cell and update the state.
579 unsafe {
580 ptr::write(self.value.get().cast(), value);
581 }
582 // Mark the OnceCell as initialised
583 self.state
584 .store(State::Initialized.into(), Ordering::Release);
585
586 // Notify the listeners that the value is initialized.
587 self.active_initializers.notify_additional(usize::MAX);
588 self.passive_waiters.notify_additional(usize::MAX);
589 Ok(())
590 } else {
591 // The cell was either initialised or is in the process of being initialised,
592 // so the given value is not needed.
593 Err(value)
594 }
595 }
596
597 /// Try to set the value of the cell.
598 ///
599 /// If the cell is already initialized, this method returns the original
600 /// value back.
601 ///
602 /// # Blocking
603 ///
604 /// In contrast to the `set` method, this method blocks the current thread of
605 /// execution instead of awaiting.
606 ///
607 /// This method should not be used in an asynchronous context. It is intended
608 /// to be used such that a `OnceCell` can be used in both asynchronous and synchronous contexts.
609 /// Calling this method in an asynchronous context may result in deadlocks.
610 ///
611 /// # Example
612 ///
613 /// ```rust
614 /// use async_lock::OnceCell;
615 ///
616 /// let cell = OnceCell::new();
617 ///
618 /// assert_eq!(cell.set_blocking(1), Ok(&1));
619 /// assert_eq!(cell.get(), Some(&1));
620 /// assert_eq!(cell.set_blocking(2), Err(2));
621 /// ```
622 #[cfg(all(feature = "std", not(target_family = "wasm")))]
623 pub fn set_blocking(&self, value: T) -> Result<&T, T> {
624 let mut value = Some(value);
625 self.get_or_init_blocking(|| value.take().unwrap());
626
627 match value {
628 Some(value) => Err(value),
629 None => {
630 // SAFETY: value was taken, so we are initialized
631 Ok(unsafe { self.get_unchecked() })
632 }
633 }
634 }
635
636 /// Wait for the cell to be initialized, optionally using a closure
637 /// to initialize the cell if it is not initialized yet.
638 #[cold]
639 async fn initialize_or_wait<E, Fut: Future<Output = Result<T, E>>, F: FnOnce() -> Fut>(
640 &self,
641 closure: F,
642 strategy: &mut impl for<'a> Strategy<'a>,
643 ) -> Result<(), E> {
644 // The event listener we're currently waiting on.
645 let mut event_listener = None;
646
647 let mut closure = Some(closure);
648
649 loop {
650 // Check the current state of the cell.
651 let state = self.state.load(Ordering::Acquire);
652
653 // Determine what we should do based on our state.
654 match state.into() {
655 State::Initialized => {
656 // The cell is initialized now, so we can return.
657 return Ok(());
658 }
659 State::Initializing => {
660 // The cell is currently initializing, or the cell is uninitialized
661 // but we do not have the ability to initialize it.
662 //
663 // We need to wait the initialization to complete.
664 if let Some(listener) = event_listener.take() {
665 strategy.wait(listener).await;
666 } else {
667 event_listener = Some(self.active_initializers.listen());
668 }
669 }
670 State::Uninitialized => {
671 // Try to move the cell into the initializing state.
672 if self
673 .state
674 .compare_exchange(
675 State::Uninitialized.into(),
676 State::Initializing.into(),
677 Ordering::AcqRel,
678 Ordering::Acquire,
679 )
680 .is_err()
681 {
682 // The cell was initialized while we were trying to
683 // initialize it.
684 continue;
685 }
686
687 // Now that we have an exclusive lock on the cell's value,
688 // we can try to initialize it.
689 let _guard = Guard(self);
690 let initializer = closure.take().unwrap();
691 match (initializer)().await {
692 Ok(value) => {
693 // Write the value into the cell and update the state.
694 unsafe {
695 ptr::write(self.value.get().cast(), value);
696 }
697 forget(_guard);
698 self.state
699 .store(State::Initialized.into(), Ordering::Release);
700
701 // Notify the listeners that the value is initialized.
702 self.active_initializers.notify_additional(usize::MAX);
703 self.passive_waiters.notify_additional(usize::MAX);
704
705 return Ok(());
706 }
707 Err(err) => {
708 // Update the state to indicate that the value is
709 // uninitialized.
710 drop(_guard);
711
712 return Err(err);
713 }
714 }
715 }
716 }
717 }
718
719 /// Set the cell's state back to `UNINITIALIZED on drop.
720 ///
721 /// If the closure panics, this ensures that the cell's state is set back to
722 /// `UNINITIALIZED` and that the next listener is notified.
723 struct Guard<'a, T>(&'a OnceCell<T>);
724
725 impl<T> Drop for Guard<'_, T> {
726 fn drop(&mut self) {
727 self.0
728 .state
729 .store(State::Uninitialized.into(), Ordering::Release);
730
731 // Notify the next initializer that it's their turn.
732 self.0.active_initializers.notify(1);
733 }
734 }
735 }
736
737 /// Get a reference to the inner value.
738 ///
739 /// # Safety
740 ///
741 /// The caller must ensure that the cell is initialized.
742 ///
743 /// # Example
744 ///
745 /// ```rust
746 /// use async_lock::OnceCell;
747 ///
748 /// # futures_lite::future::block_on(async {
749 /// let cell = OnceCell::new();
750 /// cell.set(1).await;
751 ///
752 /// // SAFETY: We know that the value is initialized, so it is safe to
753 /// // read it.
754 /// assert_eq!(unsafe { cell.get_unchecked() }, &1);
755 /// # });
756 /// ```
757 pub unsafe fn get_unchecked(&self) -> &T {
758 // SAFETY: The caller asserts that the value is initialized
759 &*self.value.get().cast()
760 }
761}
762
763impl<T> From<T> for OnceCell<T> {
764 /// Create a new, initialized `OnceCell` from an existing value.
765 ///
766 /// # Example
767 ///
768 /// ```rust
769 /// use async_lock::OnceCell;
770 ///
771 /// let cell = OnceCell::from(42);
772 /// assert_eq!(cell.get(), Some(&42));
773 /// ```
774 fn from(value: T) -> Self {
775 Self {
776 active_initializers: Event::new(),
777 passive_waiters: Event::new(),
778 state: AtomicUsize::new(State::Initialized.into()),
779 value: UnsafeCell::new(MaybeUninit::new(value)),
780 }
781 }
782}
783
784impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
785 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
786 struct Inner<'a, T>(&'a OnceCell<T>);
787
788 impl<T: fmt::Debug> fmt::Debug for Inner<'_, T> {
789 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
790 match self.0.state.load(Ordering::Acquire).into() {
791 State::Uninitialized => f.write_str("<uninitialized>"),
792 State::Initializing => f.write_str("<initializing>"),
793 State::Initialized => {
794 // SAFETY: "value" is initialized.
795 let value = unsafe { self.0.get_unchecked() };
796 fmt::Debug::fmt(value, f)
797 }
798 }
799 }
800 }
801
802 f.debug_tuple("OnceCell").field(&Inner(self)).finish()
803 }
804}
805
806impl<T> Drop for OnceCell<T> {
807 fn drop(&mut self) {
808 self.state.with_mut(|state| {
809 if State::from(*state) == State::Initialized {
810 // SAFETY: We know that the value is initialized, so it is safe to
811 // drop it.
812 unsafe { self.value.get().cast::<T>().drop_in_place() }
813 }
814 });
815 }
816}
817
818impl<T> Default for OnceCell<T> {
819 // Calls `OnceCell::new`.
820 #[inline]
821 fn default() -> Self {
822 Self::new()
823 }
824}
825
826/// Either return the result of a future now, or panic.
827#[cfg(all(feature = "std", not(target_family = "wasm")))]
828fn now_or_never<T>(f: impl Future<Output = T>) -> T {
829 use core::pin::pin;
830 use core::task::{Context, Poll, Waker};
831
832 // Poll the future exactly once.
833 let f = pin!(f);
834 let mut cx = Context::from_waker(Waker::noop());
835
836 match f.poll(&mut cx) {
837 Poll::Ready(value) => value,
838 Poll::Pending => unreachable!("future not ready"),
839 }
840}