aboutsummaryrefslogtreecommitdiff
path: root/src/sync/once_lock.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sync/once_lock.rs')
-rw-r--r--src/sync/once_lock.rs27
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() };
}
}
}