use crate::pin::Pin;
use crate::sync::atomic::AtomicU32;
use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::sys::futex::{futex_wait, futex_wake};
use crate::time::Duration;
const PARKED: u32 = u32::MAX;
const EMPTY: u32 = 0;
const NOTIFIED: u32 = 1;
pub struct Parker {
state: AtomicU32,
}
impl Parker {
pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Self { state: AtomicU32::new(EMPTY) });
}
pub unsafe fn park(self: Pin<&Self>) {
if self.state.fetch_sub(1, Acquire) == NOTIFIED {
return;
}
loop {
futex_wait(&self.state, PARKED, None);
if self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() {
return;
} else {
}
}
}
pub unsafe fn park_timeout(self: Pin<&Self>, timeout: Duration) {
if self.state.fetch_sub(1, Acquire) == NOTIFIED {
return;
}
futex_wait(&self.state, PARKED, Some(timeout));
if self.state.swap(EMPTY, Acquire) == NOTIFIED {
} else {
}
}
#[inline]
pub fn unpark(self: Pin<&Self>) {
if self.state.swap(NOTIFIED, Release) == PARKED {
futex_wake(&self.state);
}
}
}