1 #![cfg(feature = "invocation")]
2
3 use std::{
4 sync::{Arc, Barrier},
5 thread::spawn,
6 };
7
8 use jni::{
9 objects::{AutoLocal, JValue},
10 sys::jint,
11 };
12
13 mod util;
14 use util::{attach_current_thread, unwrap};
15
16 #[test]
global_ref_works_in_other_threads()17 pub fn global_ref_works_in_other_threads() {
18 const ITERS_PER_THREAD: usize = 10_000;
19
20 let env = attach_current_thread();
21 let mut join_handlers = Vec::new();
22
23 let atomic_integer = {
24 let local_ref = AutoLocal::new(
25 &env,
26 unwrap(
27 &env,
28 env.new_object(
29 "java/util/concurrent/atomic/AtomicInteger",
30 "(I)V",
31 &[JValue::from(0)],
32 ),
33 ),
34 );
35 unwrap(&env, env.new_global_ref(&local_ref))
36 };
37
38 // Test with a different number of threads (from 2 to 8)
39 for thread_num in 2..9 {
40 let barrier = Arc::new(Barrier::new(thread_num));
41
42 for _ in 0..thread_num {
43 let barrier = barrier.clone();
44 let atomic_integer = atomic_integer.clone();
45
46 let jh = spawn(move || {
47 let env = attach_current_thread();
48 barrier.wait();
49 for _ in 0..ITERS_PER_THREAD {
50 unwrap(
51 &env,
52 unwrap(
53 &env,
54 env.call_method(&atomic_integer, "incrementAndGet", "()I", &[]),
55 )
56 .i(),
57 );
58 }
59 });
60 join_handlers.push(jh);
61 }
62
63 for jh in join_handlers.drain(..) {
64 jh.join().unwrap();
65 }
66
67 let expected = (ITERS_PER_THREAD * thread_num) as jint;
68 assert_eq!(
69 expected,
70 unwrap(
71 &env,
72 unwrap(
73 &env,
74 env.call_method(&atomic_integer, "getAndSet", "(I)I", &[JValue::from(0)])
75 )
76 .i()
77 )
78 );
79 }
80 }
81