1use alloc::boxed::Box;
2use core::ffi::c_void;
3
4use crate::generated::{dispatch_group_enter, dispatch_group_wait};
5use crate::{DispatchObject, DispatchQueue, DispatchRetained, DispatchTime};
6
7use super::utils::function_wrapper;
8use super::WaitError;
9
10dispatch_object!(
11 #[doc(alias = "dispatch_group_t")]
13 #[doc(alias = "dispatch_group_s")]
14 pub struct DispatchGroup;
15);
16
17dispatch_object_not_data!(unsafe DispatchGroup);
18
19impl DispatchGroup {
20 #[inline]
22 pub fn exec_async<F>(&self, queue: &DispatchQueue, work: F)
23 where
24 F: Send + FnOnce() + 'static,
27 {
28 let work_boxed = Box::into_raw(Box::new(work)).cast::<c_void>();
29
30 unsafe { Self::exec_async_f(self, queue, work_boxed, function_wrapper::<F>) };
32 }
33
34 #[inline]
40 pub fn wait(&self, timeout: DispatchTime) -> Result<(), WaitError> {
41 let result = dispatch_group_wait(self, timeout);
42
43 match result {
44 0 => Ok(()),
45 _ => Err(WaitError::Timeout),
46 }
47 }
48
49 #[inline]
51 pub fn notify<F>(&self, queue: &DispatchQueue, work: F)
52 where
53 F: Send + FnOnce(),
54 {
55 let work_boxed = Box::into_raw(Box::new(work)).cast::<c_void>();
56
57 unsafe {
59 Self::notify_f(self, queue, work_boxed, function_wrapper::<F>);
60 }
61 }
62
63 #[inline]
65 pub fn enter(&self) -> DispatchGroupGuard {
66 unsafe { dispatch_group_enter(self) };
68
69 DispatchGroupGuard(self.retain())
70 }
71}
72
73#[derive(Debug)]
75pub struct DispatchGroupGuard(DispatchRetained<DispatchGroup>);
76
77impl DispatchGroupGuard {
78 #[inline]
80 pub fn leave(self) {
81 let _ = self;
83 }
84}
85
86impl Drop for DispatchGroupGuard {
87 #[inline]
88 fn drop(&mut self) {
89 unsafe { DispatchGroup::leave(&self.0) };
91 }
92}