use super::{Mutex, UPIntrFreeCell};
use alloc::{collections::VecDeque, sync::Arc};
use tg_task_manage::ThreadId;
pub struct Condvar {
pub inner: UPIntrFreeCell<CondvarInner>,
}
pub struct CondvarInner {
pub wait_queue: VecDeque<ThreadId>,
}
impl Condvar {
pub fn new() -> Self {
Self {
inner: unsafe {
UPIntrFreeCell::new(CondvarInner {
wait_queue: VecDeque::new(),
})
},
}
}
pub fn signal(&self) -> Option<ThreadId> {
let mut inner = self.inner.exclusive_access();
inner.wait_queue.pop_front()
}
pub fn wait_no_sched(&self, tid: ThreadId) -> bool {
self.inner.exclusive_session(|inner| {
inner.wait_queue.push_back(tid);
});
false
}
pub fn wait_with_mutex(
&self,
tid: ThreadId,
mutex: Arc<dyn Mutex>,
) -> (bool, Option<ThreadId>) {
let waking_tid = mutex.unlock().unwrap();
(mutex.lock(tid), Some(waking_tid))
}
}