1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//! waitgroup provides an interface for awaiting the completion of multiple asynchronous tasks

use std::sync::{Condvar, Mutex};

/// A waitgroup waits for a collection of tasks to complete.
/// It keeps track of tasks via shared counter
pub struct WaitGroup {
    cvar: Condvar,
    count: Mutex<usize>,
}

impl Default for WaitGroup {
    fn default() -> WaitGroup {
        WaitGroup::new(0)
    }
}

impl WaitGroup {
    /// creates a new wait group instance
    pub fn new(n: usize) -> WaitGroup {
        WaitGroup {
            cvar: Condvar::new(),
            count: Mutex::new(n),
        }
    }

    /// adds `delta` to internal counter
    pub fn add(&self, delta: usize) {
        let mut count = self.count.lock().unwrap();
        *count += delta;
        self.notify_if_empty(*count)
    }

    /// subtracts 1 from internal counter
    pub fn done(&self) {
        let mut count = self.count.lock().unwrap();
        *count -= 1;
        self.notify_if_empty(*count)
    }

    fn notify_if_empty(&self, count: usize) {
        if count <= 0 {
            self.cvar.notify_all();
        }
    }

    /// blocks the current thread until wait group is complete
    pub fn wait(&self) {
        let mut count = self.count.lock().unwrap();
        while *count > 0 {
            count = self.cvar.wait(count).unwrap();
        }
    }
}

#[test]
fn it_works() {}