apple_cf/
dispatch_queue.rs1#![allow(clippy::missing_panics_doc)]
18
19use std::ffi::{c_void, CString};
28use std::fmt;
29use std::time::Duration;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
47pub enum DispatchQoS {
48 Background = 0,
50 Utility = 1,
52 #[default]
54 Default = 2,
55 UserInitiated = 3,
57 UserInteractive = 4,
59}
60
61pub struct DispatchQueue {
74 ptr: *const c_void,
75}
76
77unsafe impl Send for DispatchQueue {}
78unsafe impl Sync for DispatchQueue {}
79
80impl DispatchQueue {
81 #[must_use]
101 pub fn new(label: &str, qos: DispatchQoS) -> Self {
102 let c_label = CString::new(label).expect("Label contains null byte");
103 let ptr = unsafe { crate::ffi::dispatch_queue_create(c_label.as_ptr(), qos as i32) };
104 assert!(!ptr.is_null(), "Failed to create dispatch queue");
105 Self { ptr }
106 }
107
108 #[must_use]
112 pub const fn as_ptr(&self) -> *const c_void {
113 self.ptr
114 }
115}
116
117impl Clone for DispatchQueue {
118 fn clone(&self) -> Self {
119 unsafe {
120 Self {
121 ptr: crate::ffi::dispatch_queue_retain(self.ptr),
122 }
123 }
124 }
125}
126
127impl Drop for DispatchQueue {
128 fn drop(&mut self) {
129 unsafe {
130 crate::ffi::dispatch_queue_release(self.ptr);
131 }
132 }
133}
134
135impl fmt::Debug for DispatchQueue {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.debug_struct("DispatchQueue")
138 .field("ptr", &self.ptr)
139 .finish()
140 }
141}
142
143impl fmt::Display for DispatchQueue {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "DispatchQueue")
146 }
147}
148
149fn timeout_ms(timeout: Option<Duration>) -> i64 {
150 timeout.map_or(-1, |duration| {
151 i64::try_from(duration.as_millis()).unwrap_or(i64::MAX)
152 })
153}
154
155#[derive(PartialEq, Eq, Hash)]
157pub struct DispatchGroup {
158 ptr: *mut c_void,
159}
160
161impl DispatchGroup {
162 #[must_use]
164 pub fn new() -> Self {
165 let ptr = unsafe { crate::ffi::acf_dispatch_group_create() };
166 assert!(!ptr.is_null(), "failed to create DispatchGroup");
167 Self { ptr }
168 }
169
170 pub fn enter(&self) {
172 unsafe { crate::ffi::acf_dispatch_group_enter(self.ptr) };
173 }
174
175 pub fn leave(&self) {
177 unsafe { crate::ffi::acf_dispatch_group_leave(self.ptr) };
178 }
179
180 #[must_use]
182 pub fn wait(&self, timeout: Option<Duration>) -> bool {
183 unsafe { crate::ffi::acf_dispatch_group_wait(self.ptr, timeout_ms(timeout)) }
184 }
185}
186
187impl Default for DispatchGroup {
188 fn default() -> Self {
189 Self::new()
190 }
191}
192
193impl Clone for DispatchGroup {
194 fn clone(&self) -> Self {
195 Self {
196 ptr: unsafe { crate::ffi::acf_object_retain(self.ptr) },
197 }
198 }
199}
200
201impl Drop for DispatchGroup {
202 fn drop(&mut self) {
203 unsafe { crate::ffi::acf_object_release(self.ptr) };
204 }
205}
206
207impl fmt::Debug for DispatchGroup {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 f.debug_struct("DispatchGroup")
210 .field("ptr", &self.ptr)
211 .finish()
212 }
213}
214
215#[derive(PartialEq, Eq, Hash)]
217pub struct DispatchSemaphore {
218 ptr: *mut c_void,
219}
220
221impl DispatchSemaphore {
222 #[must_use]
224 pub fn new(value: i64) -> Self {
225 let ptr = unsafe { crate::ffi::acf_dispatch_semaphore_create(value) };
226 assert!(!ptr.is_null(), "failed to create DispatchSemaphore");
227 Self { ptr }
228 }
229
230 #[must_use]
232 pub fn signal(&self) -> i64 {
233 unsafe { crate::ffi::acf_dispatch_semaphore_signal(self.ptr) }
234 }
235
236 #[must_use]
238 pub fn wait(&self, timeout: Option<Duration>) -> bool {
239 unsafe { crate::ffi::acf_dispatch_semaphore_wait(self.ptr, timeout_ms(timeout)) }
240 }
241}
242
243impl Clone for DispatchSemaphore {
244 fn clone(&self) -> Self {
245 Self {
246 ptr: unsafe { crate::ffi::acf_object_retain(self.ptr) },
247 }
248 }
249}
250
251impl Drop for DispatchSemaphore {
252 fn drop(&mut self) {
253 unsafe { crate::ffi::acf_object_release(self.ptr) };
254 }
255}
256
257impl fmt::Debug for DispatchSemaphore {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.debug_struct("DispatchSemaphore")
260 .field("ptr", &self.ptr)
261 .finish()
262 }
263}
264
265#[derive(PartialEq, Eq, Hash)]
267pub struct DispatchSource {
268 ptr: *mut c_void,
269}
270
271impl DispatchSource {
272 #[must_use]
274 pub fn timer(interval: Duration, leeway: Duration) -> Self {
275 let interval_ms = u64::try_from(interval.as_millis()).unwrap_or(u64::MAX);
276 let leeway_ms = u64::try_from(leeway.as_millis()).unwrap_or(u64::MAX);
277 let ptr = unsafe { crate::ffi::acf_dispatch_source_timer_create(interval_ms, leeway_ms) };
278 assert!(!ptr.is_null(), "failed to create DispatchSource timer");
279 Self { ptr }
280 }
281
282 pub fn resume(&self) {
284 unsafe { crate::ffi::acf_dispatch_source_timer_resume(self.ptr) };
285 }
286
287 pub fn cancel(&self) {
289 unsafe { crate::ffi::acf_dispatch_source_timer_cancel(self.ptr) };
290 }
291
292 #[must_use]
294 pub fn fire_count(&self) -> u64 {
295 unsafe { crate::ffi::acf_dispatch_source_timer_fire_count(self.ptr) }
296 }
297}
298
299impl Clone for DispatchSource {
300 fn clone(&self) -> Self {
301 Self {
302 ptr: unsafe { crate::ffi::acf_object_retain(self.ptr) },
303 }
304 }
305}
306
307impl Drop for DispatchSource {
308 fn drop(&mut self) {
309 unsafe { crate::ffi::acf_object_release(self.ptr) };
310 }
311}
312
313impl fmt::Debug for DispatchSource {
314 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315 f.debug_struct("DispatchSource")
316 .field("ptr", &self.ptr)
317 .field("fire_count", &self.fire_count())
318 .finish()
319 }
320}