use super::CondVar;
use crate::async_runtime::lock::Mutex;
pub struct CondWait {
condvar: CondVar,
w: Mutex<bool>,
}
impl CondWait {
pub fn new() -> Self {
Self {
condvar: CondVar::new(),
w: Mutex::new(false),
}
}
pub async fn wait(&self) {
let mut w = self.w.lock().await;
while !*w {
w = self.condvar.wait(w).await;
}
}
pub async fn signal(&self) {
*self.w.lock().await = true;
self.condvar.signal();
}
pub async fn broadcast(&self) {
*self.w.lock().await = true;
self.condvar.broadcast();
}
pub async fn reset(&self) {
*self.w.lock().await = false;
}
}
impl Default for CondWait {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
use crate::async_runtime::{block_on, spawn};
use super::*;
#[test]
fn test_cond_wait() {
block_on(async {
let cond_wait = Arc::new(CondWait::new());
let count = Arc::new(AtomicUsize::new(0));
let cond_wait_cloned = cond_wait.clone();
let count_cloned = count.clone();
let task = spawn(async move {
cond_wait_cloned.wait().await;
count_cloned.fetch_add(1, Ordering::Relaxed);
});
cond_wait.signal().await;
let _ = task.await;
cond_wait.reset().await;
assert_eq!(count.load(Ordering::Relaxed), 1);
let cond_wait_cloned = cond_wait.clone();
let count_cloned = count.clone();
let task1 = spawn(async move {
cond_wait_cloned.wait().await;
count_cloned.fetch_add(1, Ordering::Relaxed);
});
let cond_wait_cloned = cond_wait.clone();
let count_cloned = count.clone();
let task2 = spawn(async move {
cond_wait_cloned.wait().await;
count_cloned.fetch_add(1, Ordering::Relaxed);
});
cond_wait.broadcast().await;
let _ = task1.await;
let _ = task2.await;
assert_eq!(count.load(Ordering::Relaxed), 3);
});
}
}