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 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// ```