diff options
Diffstat (limited to 'src/sync/once_lock.rs')
-rw-r--r-- | src/sync/once_lock.rs | 27 |
1 files changed, 6 insertions, 21 deletions
diff --git a/src/sync/once_lock.rs b/src/sync/once_lock.rs index c1fefc9..e057aca 100644 --- a/src/sync/once_lock.rs +++ b/src/sync/once_lock.rs @@ -4,13 +4,10 @@ use core::cell::UnsafeCell; use core::mem::MaybeUninit; -use core::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; pub(crate) struct OnceLock<T> { once: Once, - // Once::is_completed requires Rust 1.43, so use this to track of whether they have been initialized. - is_initialized: AtomicBool, value: UnsafeCell<MaybeUninit<T>>, // Unlike std::sync::OnceLock, we don't need PhantomData here because // we don't use #[may_dangle]. @@ -25,7 +22,6 @@ impl<T> OnceLock<T> { pub(crate) const fn new() -> Self { Self { once: Once::new(), - is_initialized: AtomicBool::new(false), value: UnsafeCell::new(MaybeUninit::uninit()), } } @@ -50,37 +46,26 @@ impl<T> OnceLock<T> { F: FnOnce() -> T, { // Fast path check - if self.is_initialized() { + if self.once.is_completed() { // SAFETY: The inner value has been initialized return unsafe { self.get_unchecked() }; } self.initialize(f); - debug_assert!(self.is_initialized()); - // SAFETY: The inner value has been initialized unsafe { self.get_unchecked() } } - #[inline] - fn is_initialized(&self) -> bool { - self.is_initialized.load(Ordering::Acquire) - } - #[cold] fn initialize<F>(&self, f: F) where F: FnOnce() -> T, { - let slot = self.value.get().cast::<T>(); - let is_initialized = &self.is_initialized; + let slot = self.value.get(); self.once.call_once(|| { let value = f(); - unsafe { - slot.write(value); - } - is_initialized.store(true, Ordering::Release); + unsafe { slot.write(MaybeUninit::new(value)) } }); } @@ -88,16 +73,16 @@ impl<T> OnceLock<T> { /// /// The value must be initialized unsafe fn get_unchecked(&self) -> &T { - debug_assert!(self.is_initialized()); + debug_assert!(self.once.is_completed()); &*self.value.get().cast::<T>() } } impl<T> Drop for OnceLock<T> { fn drop(&mut self) { - if self.is_initialized() { + if self.once.is_completed() { // SAFETY: The inner value has been initialized - unsafe { self.value.get().cast::<T>().drop_in_place() }; + unsafe { (*self.value.get()).assume_init_drop() }; } } } |