dispatcher.rs

 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 parking::{Parker, Unparker};
13use parking_lot::Mutex;
14use std::{ffi::c_void, sync::Arc, time::Duration};
15
16include!(concat!(env!("OUT_DIR"), "/dispatch_sys.rs"));
17
18pub fn dispatch_get_main_queue() -> dispatch_queue_t {
19    unsafe { &_dispatch_main_q as *const _ as dispatch_queue_t }
20}
21
22pub struct MacDispatcher {
23    parker: Arc<Mutex<Parker>>,
24}
25
26impl MacDispatcher {
27    pub fn new() -> Self {
28        MacDispatcher {
29            parker: Arc::new(Mutex::new(Parker::new())),
30        }
31    }
32}
33
34impl PlatformDispatcher for MacDispatcher {
35    fn is_main_thread(&self) -> bool {
36        let is_main_thread: BOOL = unsafe { msg_send![class!(NSThread), isMainThread] };
37        is_main_thread == YES
38    }
39
40    fn dispatch(&self, runnable: Runnable) {
41        unsafe {
42            dispatch_async_f(
43                dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.try_into().unwrap(), 0),
44                runnable.into_raw() as *mut c_void,
45                Some(trampoline),
46            );
47        }
48    }
49
50    fn dispatch_on_main_thread(&self, runnable: Runnable) {
51        unsafe {
52            dispatch_async_f(
53                dispatch_get_main_queue(),
54                runnable.into_raw() as *mut c_void,
55                Some(trampoline),
56            );
57        }
58    }
59
60    fn dispatch_after(&self, duration: Duration, runnable: Runnable) {
61        unsafe {
62            let queue =
63                dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.try_into().unwrap(), 0);
64            let when = dispatch_time(DISPATCH_TIME_NOW as u64, duration.as_nanos() as i64);
65            dispatch_after_f(
66                when,
67                queue,
68                runnable.into_raw() as *mut c_void,
69                Some(trampoline),
70            );
71        }
72    }
73
74    fn poll(&self, _background_only: bool) -> bool {
75        false
76    }
77
78    fn park(&self) {
79        self.parker.lock().park()
80    }
81
82    fn unparker(&self) -> Unparker {
83        self.parker.lock().unparker()
84    }
85}
86
87extern "C" fn trampoline(runnable: *mut c_void) {
88    let task = unsafe { Runnable::from_raw(runnable as *mut ()) };
89    task.run();
90}