use std::{
panic::Location,
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
task::Waker,
};
use crate::native::sync::{Condvar, Mutex, MutexGuard};
pub(crate) struct Token {
cv: Condvar,
woken: Mutex<bool>,
}
impl Token {
pub(crate) fn new() -> Arc<Self> {
Arc::new(Self {
woken: Mutex::default(),
cv: Condvar::default(),
})
}
pub(crate) fn fire(&self) {
{
let mut g = self.woken.lock();
*g = true;
}
self.cv.notify_all();
}
pub(crate) fn wait(&self) {
wait_set(&self.cv, self.woken.lock());
}
}
fn wait_set(cv: &Condvar, mut woken: MutexGuard<'_, bool>) {
while !*woken {
woken = cv.wait(woken);
}
}
pub(crate) enum Wake {
Sync(Arc<Token>),
Task {
waker: Waker,
granted: Arc<AtomicBool>,
task: Option<(u64, &'static Location<'static>)>,
},
}
impl Wake {
pub(crate) fn fire(self) {
match self {
Self::Sync(t) => t.fire(),
Self::Task { waker, .. } => waker.wake(),
}
}
pub(crate) fn is_task(&self) -> bool {
matches!(self, Self::Task { .. })
}
pub(crate) fn task(&self) -> Option<(u64, &'static Location<'static>)> {
match self {
Self::Task { task, .. } => *task,
Self::Sync(_) => None,
}
}
pub(crate) fn mark_granted_under_lock(&self) {
if let Self::Task { granted, .. } = self {
granted.store(true, Ordering::Release);
}
}
}