medea_jason/platform/dart/executor/
mod.rs1mod task;
4
5use std::{
6 ptr,
7 sync::{Arc, atomic, atomic::AtomicI64},
8};
9
10use dart_sys::{
11 _Dart_CObject__bindgen_ty_1, Dart_CObject,
12 Dart_CObject_Type_Dart_CObject_kInt64, Dart_Port,
13};
14
15pub use self::task::Task;
16use crate::{api::propagate_panic, platform::utils::dart_api};
17
18pub fn spawn(fut: impl Future<Output = ()> + 'static) {
20 Task::spawn(Box::pin(fut));
21}
22
23type AtomicDartPort = AtomicI64;
25
26static WAKE_PORT: AtomicDartPort = AtomicI64::new(0);
32
33#[unsafe(no_mangle)]
42pub unsafe extern "C" fn rust_executor_init(wake_port: Dart_Port) {
43 WAKE_PORT.store(wake_port, atomic::Ordering::Release);
44}
45
46#[unsafe(no_mangle)]
56pub unsafe extern "C" fn rust_executor_poll_task(task: ptr::NonNull<Task>) {
57 propagate_panic(move || unsafe { Arc::from_raw(task.as_ptr()).poll() });
58}
59
60fn task_wake(task: Arc<Task>) {
70 let wake_port = WAKE_PORT.load(atomic::Ordering::Acquire);
71 assert!(wake_port > 0, "`WAKE_PORT` address must be initialized");
72 let task = Arc::into_raw(task);
73
74 let mut task_addr = Dart_CObject {
75 type_: Dart_CObject_Type_Dart_CObject_kInt64,
76 value: _Dart_CObject__bindgen_ty_1 { as_int64: task as i64 },
77 };
78
79 let enqueued =
80 unsafe { dart_api::post_c_object(wake_port, &raw mut task_addr) };
81 if !enqueued {
82 log::warn!("Could not send message to Dart's native port");
83 unsafe {
84 drop(Arc::from_raw(task));
85 }
86 }
87}