1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use jni::objects::JValue;
use jni::sys::{jobject, JNIEnv};
use jni::NativeMethod;

use super::{Env, Reference};

pub struct Runnable {
    reference: Reference,
}

struct RunnableClosure(Box<dyn FnOnce(&Env) + Send>);

impl Runnable {
    pub fn new<F>(env: &Env, closure: F) -> Runnable
    where
        F: FnOnce(&Env) + Send + 'static,
    {
        extern "C" fn main(env: *mut JNIEnv, _: jobject, data: i64) {
            unsafe {
                log::error!("Invoking closure.");
                let closure = Box::<RunnableClosure>::from_raw(data as *mut _);
                closure.0(&Env::new(env));
            }
        }

        unsafe {
            env.register_natives(
                "com/glacyr/polyhorn/Runnable",
                vec![NativeMethod {
                    name: "main".to_owned().into(),
                    sig: "(J)V".to_owned().into(),
                    fn_ptr: main as *mut _,
                }],
            );

            let closure = Box::new(RunnableClosure(Box::new(closure)));
            Runnable {
                reference: env.retain(env.call_constructor(
                    "com/glacyr/polyhorn/Runnable",
                    "(J)V",
                    &[JValue::Long(Box::into_raw(closure) as i64)],
                )),
            }
        }
    }

    pub fn queue(self, env: &Env) {
        log::error!("Queueing runnable.");
        unsafe {
            env.call_method(self.reference.as_object(), "queue", "()V", &[]);
        }
    }
}