1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5use crate::PlatformDispatcher;
6use async_task::Runnable;
7use objc::{
8 class, msg_send,
9 runtime::{BOOL, YES},
10 sel, sel_impl,
11};
12use std::{
13 ffi::c_void,
14 time::{Duration, SystemTime},
15};
16
17include!(concat!(env!("OUT_DIR"), "/dispatch_sys.rs"));
18
19pub fn dispatch_get_main_queue() -> dispatch_queue_t {
20 unsafe { &_dispatch_main_q as *const _ as dispatch_queue_t }
21}
22
23pub struct MacDispatcher;
24
25impl PlatformDispatcher for MacDispatcher {
26 fn is_main_thread(&self) -> bool {
27 let is_main_thread: BOOL = unsafe { msg_send![class!(NSThread), isMainThread] };
28 is_main_thread == YES
29 }
30
31 fn dispatch(&self, runnable: Runnable) {
32 unsafe {
33 dispatch_async_f(
34 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.try_into().unwrap(), 0),
35 runnable.into_raw() as *mut c_void,
36 Some(trampoline),
37 );
38 }
39 }
40
41 fn dispatch_on_main_thread(&self, runnable: Runnable) {
42 unsafe {
43 dispatch_async_f(
44 dispatch_get_main_queue(),
45 runnable.into_raw() as *mut c_void,
46 Some(trampoline),
47 );
48 }
49 }
50
51 fn dispatch_after(&self, duration: Duration, runnable: Runnable) {
52 let now = SystemTime::now();
53 let after_duration = now
54 .duration_since(SystemTime::UNIX_EPOCH)
55 .unwrap()
56 .as_nanos() as u64
57 + duration.as_nanos() as u64;
58 unsafe {
59 let queue =
60 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.try_into().unwrap(), 0);
61 let when = dispatch_time(0, after_duration as i64);
62 dispatch_after_f(
63 when,
64 queue,
65 runnable.into_raw() as *mut c_void,
66 Some(trampoline),
67 );
68 }
69 }
70
71 fn poll(&self) -> bool {
72 false
73 }
74}
75
76extern "C" fn trampoline(runnable: *mut c_void) {
77 let task = unsafe { Runnable::from_raw(runnable as *mut ()) };
78 task.run();
79}
80
81// #include <dispatch/dispatch.h>
82
83// int main(void) {
84
85// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
86// // Do some lengthy background work here...
87// printf("Background Work\n");
88
89// dispatch_async(dispatch_get_main_queue(), ^{
90// // Once done, update your UI on the main queue here.
91// printf("UI Updated\n");
92
93// });
94// });
95
96// sleep(3); // prevent the program from terminating immediately
97
98// return 0;
99// }
100// ```