use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc, Condvar, Mutex,
};
#[derive(Default)]
struct Wg {
counter: AtomicUsize,
mu: Mutex<bool>,
condvar: Condvar,
}
#[derive(Default)]
pub struct WaitGroup(Arc<Wg>);
impl WaitGroup {
pub fn wait(&self) {
let mut mutex = self.0.mu.lock().expect("Cant get the lock");
loop {
if self.0.counter.load(Ordering::Relaxed) == 0 {
break;
}
mutex = self
.0
.condvar
.wait(mutex)
.expect("Cant block the current thread");
}
}
}
impl Clone for WaitGroup {
fn clone(&self) -> Self {
self.0.counter.fetch_add(1, Ordering::Relaxed);
Self(self.0.clone())
}
}
impl Drop for WaitGroup {
fn drop(&mut self) {
self.0.counter.fetch_sub(1, Ordering::Relaxed);
self.0.condvar.notify_one();
}
}
#[cfg(test)]
mod mod_wait_group_tests {
use super::WaitGroup;
#[test]
fn test_if_zero_count_must_not_block() {
let wg = WaitGroup::default();
wg.wait();
}
}