| ... | ... | @@ -1,22 +1,34 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const WaitGroup = @This(); |
| 3 | 3 | |
| 4 | lock: std.Mutex = .{}, |
| 4 | 5 | counter: usize = 0, |
| 5 | | event: ?*std.AutoResetEvent = null, |
| 6 | event: std.AutoResetEvent = .{}, |
| 6 | 7 | |
| 7 | 8 | pub fn start(self: *WaitGroup) void { |
| 8 | | _ = @atomicRmw(usize, &self.counter, .Add, 1, .SeqCst); |
| 9 | const held = self.lock.acquire(); |
| 10 | defer held.release(); |
| 11 | |
| 12 | self.counter += 1; |
| 9 | 13 | } |
| 10 | 14 | |
| 11 | 15 | pub fn stop(self: *WaitGroup) void { |
| 12 | | if (@atomicRmw(usize, &self.counter, .Sub, 1, .SeqCst) == 1) |
| 13 | | if (@atomicRmw(?*std.AutoResetEvent, &self.event, .Xchg, null, .SeqCst)) |event| |
| 14 | | event.set(); |
| 16 | const held = self.lock.acquire(); |
| 17 | defer held.release(); |
| 18 | |
| 19 | self.counter -= 1; |
| 20 | if (self.counter == 0) |
| 21 | self.event.set(); |
| 15 | 22 | } |
| 16 | 23 | |
| 17 | 24 | pub fn wait(self: *WaitGroup) void { |
| 18 | | var event = std.AutoResetEvent{}; |
| 19 | | @atomicStore(?*std.AutoResetEvent, &self.event, &event, .SeqCst); |
| 20 | | if (@atomicLoad(usize, &self.counter, .SeqCst) != 0) |
| 21 | | event.wait(); |
| 25 | { |
| 26 | const held = self.lock.acquire(); |
| 27 | defer held.release(); |
| 28 | |
| 29 | if (self.counter == 0) |
| 30 | return; |
| 31 | } |
| 32 | |
| 33 | self.event.wait(); |
| 22 | 34 | } |