1use ::jni::{
2 errors::Result,
3 objects::{JMethodID, JObject, JClass},
4 signature::JavaType,
5 JNIEnv,
6};
7use std::task::Waker;
8
9pub fn waker<'a: 'b, 'b>(env: &'b JNIEnv<'a>, waker: Waker) -> Result<JObject<'a>> {
20 let runnable = crate::ops::fn_once_runnable(env, |_e, _o| waker.wake())?;
21
22 let obj = env.new_object(
23 JClass::from(crate::classcache::get_class("io/github/gedgygedgy/rust/task/Waker").unwrap().as_obj()),
24 "(Lio/github/gedgygedgy/rust/ops/FnRunnable;)V",
25 &[runnable.into()],
26 )?;
27 Ok(obj)
28}
29
30pub struct JPollResult<'a: 'b, 'b> {
37 internal: JObject<'a>,
38 get: JMethodID<'a>,
39 env: &'b JNIEnv<'a>,
40}
41
42impl<'a: 'b, 'b> JPollResult<'a, 'b> {
43 pub fn from_env(env: &'b JNIEnv<'a>, obj: JObject<'a>) -> Result<Self> {
52 let get = env.get_method_id(
53 JClass::from(crate::classcache::get_class("io/github/gedgygedgy/rust/task/PollResult").unwrap().as_obj()),
54 "get",
55 "()Ljava/lang/Object;")?;
56 Ok(Self {
57 internal: obj,
58 get,
59 env,
60 })
61 }
62
63 pub fn get(&self) -> Result<JObject<'a>> {
67 self.env
68 .call_method_unchecked(
69 self.internal,
70 self.get,
71 JavaType::Object("java/lang/Object".into()),
72 &[],
73 )?
74 .l()
75 }
76}
77
78impl<'a: 'b, 'b> ::std::ops::Deref for JPollResult<'a, 'b> {
79 type Target = JObject<'a>;
80
81 fn deref(&self) -> &Self::Target {
82 &self.internal
83 }
84}
85
86impl<'a: 'b, 'b> From<JPollResult<'a, 'b>> for JObject<'a> {
87 fn from(other: JPollResult<'a, 'b>) -> JObject<'a> {
88 other.internal
89 }
90}
91
92#[cfg(test)]
93mod test {
94 use crate::test_utils;
95 use std::sync::Arc;
96
97 #[test]
98 fn test_waker_wake() {
99 test_utils::JVM_ENV.with(|env| {
100 let data = Arc::new(test_utils::TestWakerData::new());
101 assert_eq!(Arc::strong_count(&data), 1);
102 assert_eq!(data.value(), false);
103
104 let waker = crate::test_utils::test_waker(&data);
105 assert_eq!(Arc::strong_count(&data), 2);
106 assert_eq!(data.value(), false);
107
108 let jwaker = super::waker(env, waker).unwrap();
109 assert_eq!(Arc::strong_count(&data), 2);
110 assert_eq!(data.value(), false);
111
112 env.call_method(jwaker, "wake", "()V", &[]).unwrap();
113 assert_eq!(Arc::strong_count(&data), 1);
114 assert_eq!(data.value(), true);
115 data.set_value(false);
116
117 env.call_method(jwaker, "wake", "()V", &[]).unwrap();
118 assert_eq!(Arc::strong_count(&data), 1);
119 assert_eq!(data.value(), false);
120 });
121 }
122
123 #[test]
124 fn test_waker_close_wake() {
125 test_utils::JVM_ENV.with(|env| {
126 let data = Arc::new(test_utils::TestWakerData::new());
127 assert_eq!(Arc::strong_count(&data), 1);
128 assert_eq!(data.value(), false);
129
130 let waker = crate::test_utils::test_waker(&data);
131 assert_eq!(Arc::strong_count(&data), 2);
132 assert_eq!(data.value(), false);
133
134 let jwaker = super::waker(env, waker).unwrap();
135 assert_eq!(Arc::strong_count(&data), 2);
136 assert_eq!(data.value(), false);
137
138 env.call_method(jwaker, "close", "()V", &[]).unwrap();
139 assert_eq!(Arc::strong_count(&data), 1);
140 assert_eq!(data.value(), false);
141
142 env.call_method(jwaker, "wake", "()V", &[]).unwrap();
143 assert_eq!(Arc::strong_count(&data), 1);
144 assert_eq!(data.value(), false);
145 });
146 }
147}