|
@@ -5,13 +5,13 @@ use core::sync::atomic::Ordering::SeqCst;
|
|
use platform::types::*;
|
|
use platform::types::*;
|
|
|
|
|
|
const UNINITIALIZED: c_int = 0;
|
|
const UNINITIALIZED: c_int = 0;
|
|
-const INITIALIZING: c_int = 1;
|
|
|
|
-const WAITING: c_int = 2;
|
|
|
|
-const INITIALIZED: c_int = 3;
|
|
|
|
|
|
+const INITIALIZING: c_int = 1;
|
|
|
|
+const WAITING: c_int = 2;
|
|
|
|
+const INITIALIZED: c_int = 3;
|
|
|
|
|
|
pub struct Once<T> {
|
|
pub struct Once<T> {
|
|
status: AtomicLock,
|
|
status: AtomicLock,
|
|
- data: UnsafeCell<MaybeUninit<T>>
|
|
|
|
|
|
+ data: UnsafeCell<MaybeUninit<T>>,
|
|
}
|
|
}
|
|
unsafe impl<T: Send> Send for Once<T> {}
|
|
unsafe impl<T: Send> Send for Once<T> {}
|
|
unsafe impl<T: Send> Sync for Once<T> {}
|
|
unsafe impl<T: Send> Sync for Once<T> {}
|
|
@@ -19,13 +19,17 @@ impl<T> Once<T> {
|
|
pub const fn new() -> Self {
|
|
pub const fn new() -> Self {
|
|
Self {
|
|
Self {
|
|
status: AtomicLock::new(UNINITIALIZED),
|
|
status: AtomicLock::new(UNINITIALIZED),
|
|
- data: UnsafeCell::new(MaybeUninit::uninit())
|
|
|
|
|
|
+ data: UnsafeCell::new(MaybeUninit::uninit()),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pub fn call_once<F>(&self, f: F) -> &mut T
|
|
pub fn call_once<F>(&self, f: F) -> &mut T
|
|
- where F: FnOnce() -> T
|
|
|
|
|
|
+ where
|
|
|
|
+ F: FnOnce() -> T,
|
|
{
|
|
{
|
|
- match self.status.compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst) {
|
|
|
|
|
|
+ match self
|
|
|
|
+ .status
|
|
|
|
+ .compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst)
|
|
|
|
+ {
|
|
UNINITIALIZED => {
|
|
UNINITIALIZED => {
|
|
// We now have a lock, let's initiate things!
|
|
// We now have a lock, let's initiate things!
|
|
let ret = unsafe { &mut *self.data.get() }.write(f());
|
|
let ret = unsafe { &mut *self.data.get() }.write(f());
|
|
@@ -35,28 +39,29 @@ impl<T> Once<T> {
|
|
// At least one thread is waiting on this to finish
|
|
// At least one thread is waiting on this to finish
|
|
self.status.notify_all();
|
|
self.status.notify_all();
|
|
}
|
|
}
|
|
- },
|
|
|
|
|
|
+ }
|
|
INITIALIZING | WAITING => self.status.wait_until(
|
|
INITIALIZING | WAITING => self.status.wait_until(
|
|
|lock| match lock.load(SeqCst) {
|
|
|lock| match lock.load(SeqCst) {
|
|
WAITING => AttemptStatus::Waiting,
|
|
WAITING => AttemptStatus::Waiting,
|
|
INITIALIZED => AttemptStatus::Desired,
|
|
INITIALIZED => AttemptStatus::Desired,
|
|
- _ => AttemptStatus::Other
|
|
|
|
|
|
+ _ => AttemptStatus::Other,
|
|
},
|
|
},
|
|
- |lock| match lock.compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst).unwrap_or_else(|e| e) {
|
|
|
|
|
|
+ |lock| match lock
|
|
|
|
+ .compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst)
|
|
|
|
+ .unwrap_or_else(|e| e)
|
|
|
|
+ {
|
|
WAITING => AttemptStatus::Waiting,
|
|
WAITING => AttemptStatus::Waiting,
|
|
INITIALIZED => AttemptStatus::Desired,
|
|
INITIALIZED => AttemptStatus::Desired,
|
|
- _ => AttemptStatus::Other
|
|
|
|
|
|
+ _ => AttemptStatus::Other,
|
|
},
|
|
},
|
|
- WAITING
|
|
|
|
|
|
+ WAITING,
|
|
),
|
|
),
|
|
INITIALIZED => (),
|
|
INITIALIZED => (),
|
|
- _ => unreachable!("invalid state for Once<T>")
|
|
|
|
|
|
+ _ => unreachable!("invalid state for Once<T>"),
|
|
}
|
|
}
|
|
|
|
|
|
// At this point the data must be initialized!
|
|
// At this point the data must be initialized!
|
|
- unsafe {
|
|
|
|
- &mut *(&mut *self.data.get()).as_mut_ptr()
|
|
|
|
- }
|
|
|
|
|
|
+ unsafe { &mut *(&mut *self.data.get()).as_mut_ptr() }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
impl<T> Default for Once<T> {
|
|
impl<T> Default for Once<T> {
|