Use futex directly in waitval.
This commit is contained in:
+9
-8
@@ -1,14 +1,13 @@
|
||||
// Semaphores need one post per wait, Once doesn't have separate post and wait, and while mutexes
|
||||
// wait for releasing the lock, it calls notify_one and needs locking again to access the value.
|
||||
|
||||
use core::cell::UnsafeCell;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::sync::atomic::Ordering;
|
||||
use core::sync::atomic::{AtomicU32 as AtomicUint, Ordering};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// An unsafe "one thread to one thread" synchronization primitive. Used for and modeled after
|
||||
/// pthread_join only, at the moment.
|
||||
pub struct Waitval<T> {
|
||||
state: AtomicLock,
|
||||
state: AtomicUint,
|
||||
value: UnsafeCell<MaybeUninit<T>>,
|
||||
}
|
||||
|
||||
@@ -18,20 +17,22 @@ unsafe impl<T: Send + Sync> Sync for Waitval<T> {}
|
||||
impl<T> Waitval<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
state: AtomicLock::new(0),
|
||||
state: AtomicUint::new(0),
|
||||
value: UnsafeCell::new(MaybeUninit::uninit()),
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Caller must ensure both (1) that the value has not yet been initialized, and (2)
|
||||
// that this is never run by more than one thread simultaneously.
|
||||
pub unsafe fn post(&self, value: T) {
|
||||
self.value.get().write(MaybeUninit::new(value));
|
||||
self.state.store(1, Ordering::Release);
|
||||
self.state.notify_all();
|
||||
crate::sync::futex_wake(&self.state, i32::MAX);
|
||||
}
|
||||
|
||||
pub fn wait(&self) -> &T {
|
||||
while self.state.load(Ordering::Acquire) == 0 {
|
||||
self.state.wait_if(0, None);
|
||||
crate::sync::futex_wait(&self.state, 0, None);
|
||||
}
|
||||
|
||||
unsafe { (*self.value.get()).assume_init_ref() }
|
||||
|
||||
Reference in New Issue
Block a user