polyhorn_android_sys/
runnable.rs

1use jni::objects::JValue;
2use jni::sys::{jobject, JNIEnv};
3use jni::NativeMethod;
4
5use super::{Env, Reference};
6
7pub struct Runnable {
8    reference: Reference,
9}
10
11struct RunnableClosure(Box<dyn FnOnce(&Env) + Send>);
12
13impl Runnable {
14    pub fn new<F>(env: &Env, closure: F) -> Runnable
15    where
16        F: FnOnce(&Env) + Send + 'static,
17    {
18        extern "C" fn main(env: *mut JNIEnv, _: jobject, data: i64) {
19            unsafe {
20                log::error!("Invoking closure.");
21                let closure = Box::<RunnableClosure>::from_raw(data as *mut _);
22                closure.0(&Env::new(env));
23            }
24        }
25
26        unsafe {
27            env.register_natives(
28                "com/glacyr/polyhorn/Runnable",
29                vec![NativeMethod {
30                    name: "main".to_owned().into(),
31                    sig: "(J)V".to_owned().into(),
32                    fn_ptr: main as *mut _,
33                }],
34            );
35
36            let closure = Box::new(RunnableClosure(Box::new(closure)));
37            Runnable {
38                reference: env.retain(env.call_constructor(
39                    "com/glacyr/polyhorn/Runnable",
40                    "(J)V",
41                    &[JValue::Long(Box::into_raw(closure) as i64)],
42                )),
43            }
44        }
45    }
46
47    pub fn queue(self, env: &Env) {
48        log::error!("Queueing runnable.");
49        unsafe {
50            env.call_method(self.reference.as_object(), "queue", "()V", &[]);
51        }
52    }
53}