moirai_sync/sync/
wait_group.rs1#![expect(
2 clippy::unwrap_used,
3 reason = "ratchet MOIRAI-UNWRAP-1: pre-existing debt"
4)]
5
6use std::fmt;
7use std::sync::{Condvar, Mutex};
8
9pub struct WaitGroup {
12 state: Mutex<WaitGroupState>,
13 cond: Condvar,
14}
15
16struct WaitGroupState {
17 counter: u64,
18}
19
20impl fmt::Debug for WaitGroup {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 let state = self.state.lock().unwrap();
23 f.debug_struct("WaitGroup")
24 .field("counter", &state.counter)
25 .finish()
26 }
27}
28
29impl Default for WaitGroup {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl WaitGroup {
36 pub fn new() -> Self {
38 Self {
39 state: Mutex::new(WaitGroupState { counter: 0 }),
40 cond: Condvar::new(),
41 }
42 }
43
44 pub fn add(&self, delta: u64) {
46 if delta == 0 {
47 return;
48 }
49 let mut state = self.state.lock().unwrap();
50 state.counter = state
51 .counter
52 .checked_add(delta)
53 .expect("WaitGroup counter overflow");
54 }
55
56 pub fn done(&self) {
58 let mut state = self.state.lock().unwrap();
59 if state.counter == 0 {
60 panic!("WaitGroup counter decremented below zero");
61 }
62 state.counter -= 1;
63 if state.counter == 0 {
64 self.cond.notify_all();
65 }
66 }
67
68 pub fn wait(&self) {
70 let mut state = self.state.lock().unwrap();
71 while state.counter > 0 {
72 state = self.cond.wait(state).unwrap();
73 }
74 }
75}