Better on_app_quit

Co-authored-by: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Conrad Irwin 2025-05-12 22:28:26 +02:00
parent fa3d0aaed4
commit 155e29f5d9
9 changed files with 147 additions and 78 deletions

View file

@ -4,6 +4,14 @@
use crate::{PlatformDispatcher, TaskLabel};
use async_task::Runnable;
use block::{Block, ConcreteBlock, RcBlock};
use core_foundation::{
base::CFTypeRef,
runloop::{
CFRunLoopRef, CFRunLoopRunInMode, CFRunLoopWakeUp, kCFRunLoopCommonModes,
kCFRunLoopDefaultMode,
},
};
use objc::{
class, msg_send,
runtime::{BOOL, YES},
@ -11,7 +19,9 @@ use objc::{
};
use parking::{Parker, Unparker};
use parking_lot::Mutex;
use smol::io::BlockOn;
use std::{
cell::Cell,
ffi::c_void,
ptr::{NonNull, addr_of},
sync::Arc,
@ -64,11 +74,21 @@ impl PlatformDispatcher for MacDispatcher {
}
fn dispatch_on_main_thread(&self, runnable: Runnable) {
use core_foundation::runloop::CFRunLoopGetMain;
unsafe {
dispatch_async_f(
dispatch_get_main_queue(),
runnable.into_raw().as_ptr() as *mut c_void,
Some(trampoline),
let mut runnable = Cell::new(Some(runnable));
let main_run_loop = CFRunLoopGetMain();
let block = ConcreteBlock::new(move || {
if let Some(runnable) = runnable.take() {
runnable.run();
}
})
.copy();
CFRunLoopPerformBlock(
main_run_loop,
kCFRunLoopDefaultMode as _,
&*block as *const Block<_, _> as _,
);
}
}
@ -87,6 +107,13 @@ impl PlatformDispatcher for MacDispatcher {
}
}
fn tick(&self, background_only: bool) -> bool {
unsafe {
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0., 0);
}
true
}
fn park(&self, timeout: Option<Duration>) -> bool {
if let Some(timeout) = timeout {
self.parker.lock().park_timeout(timeout)
@ -105,3 +132,7 @@ extern "C" fn trampoline(runnable: *mut c_void) {
let task = unsafe { Runnable::<()>::from_raw(NonNull::new_unchecked(runnable as *mut ())) };
task.run();
}
unsafe extern "C" {
fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: *const c_void);
}