1use std::sync::atomic::Ordering;
2use std::sync::{Arc, Condvar, Mutex};
3use std::time::Duration;
4
5use crate::padded_type::PaddedAtomicUsize;
6
7#[derive(Clone)]
14pub struct TaskFuture {
15 remaining: Arc<PaddedAtomicUsize>,
16 state: Arc<(Mutex<()>, Condvar)>,
17}
18
19impl TaskFuture {
20 pub(crate) fn new(task_count: usize) -> Self {
22 TaskFuture {
23 remaining: Arc::new(PaddedAtomicUsize::new(task_count)),
24 state: Arc::new((Mutex::new(()), Condvar::new())),
25 }
26 }
27
28 pub fn is_complete(&self) -> bool {
33 self.remaining.load(Ordering::Acquire) == 0
34 }
35
36 pub fn wait(self) {
42 if self.is_complete() {
43 return;
44 }
45
46 let (lock, cvar) = &*self.state;
47 let mut guard = lock.lock().unwrap();
48
49 while !self.is_complete() {
50 guard = cvar.wait(guard).unwrap();
51 }
52 }
53
54 pub fn wait_timeout(self, timeout: Duration) -> bool {
59 if self.is_complete() {
60 return true;
61 }
62
63 let (lock, cvar) = &*self.state;
64 let mut guard = lock.lock().unwrap();
65
66 while !self.is_complete() {
67 let (new_guard, timeout_result) = cvar.wait_timeout(guard, timeout).unwrap();
68 guard = new_guard;
69 if timeout_result.timed_out() {
70 return self.is_complete();
71 }
72 }
73 true
74 }
75
76 pub(crate) fn complete_many(&self, count: usize) {
78 let remaining_count = self.remaining.fetch_sub(count, Ordering::Release);
79
80 if remaining_count == count {
82 let (lock, cvar) = &*self.state;
83 let _guard = lock.lock().unwrap();
84 cvar.notify_all();
85 }
86 }
87}