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