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 mut env = attach_current_thread();
21 let mut join_handlers = Vec::new();
22
23 let atomic_integer = {
24 let local_ref = AutoLocal::new(
25 unwrap(
26 env.new_object(
27 "java/util/concurrent/atomic/AtomicInteger",
28 "(I)V",
29 &[JValue::from(0)],
30 ),
31 &env,
32 ),
33 &env,
34 );
35 unwrap(env.new_global_ref(&local_ref), &env)
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 mut env = attach_current_thread();
48 barrier.wait();
49 for _ in 0..ITERS_PER_THREAD {
50 unwrap(
51 unwrap(
52 env.call_method(&atomic_integer, "incrementAndGet", "()I", &[]),
53 &env,
54 )
55 .i(),
56 &env,
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 unwrap(
72 env.call_method(&atomic_integer, "getAndSet", "(I)I", &[JValue::from(0)]),
73 &env,
74 )
75 .i(),
76 &env,
77 )
78 );
79 }
80 }
81