1 | use crossbeam_utils::thread; |
2 | use rayon_core::ThreadPoolBuilder; |
3 | |
4 | #[derive(PartialEq, Eq, Debug)] |
5 | struct Local(i32); |
6 | |
7 | scoped_tls::scoped_thread_local!(static LOCAL: Local); |
8 | |
9 | #[test] |
10 | #[cfg_attr (any(target_os = "emscripten" , target_family = "wasm" ), ignore)] |
11 | fn missing_scoped_tls() { |
12 | LOCAL.set(&Local(42), || { |
13 | let pool = ThreadPoolBuilder::new() |
14 | .build() |
15 | .expect("thread pool created" ); |
16 | |
17 | // `LOCAL` is not set in the pool. |
18 | pool.install(|| { |
19 | assert!(!LOCAL.is_set()); |
20 | }); |
21 | }); |
22 | } |
23 | |
24 | #[test] |
25 | #[cfg_attr (any(target_os = "emscripten" , target_family = "wasm" ), ignore)] |
26 | fn spawn_scoped_tls_threadpool() { |
27 | LOCAL.set(&Local(42), || { |
28 | LOCAL.with(|x| { |
29 | thread::scope(|scope| { |
30 | let pool = ThreadPoolBuilder::new() |
31 | .spawn_handler(move |thread| { |
32 | scope |
33 | .builder() |
34 | .spawn(move |_| { |
35 | // Borrow the same local value in the thread pool. |
36 | LOCAL.set(x, || thread.run()) |
37 | }) |
38 | .map(|_| ()) |
39 | }) |
40 | .build() |
41 | .expect("thread pool created" ); |
42 | |
43 | // The pool matches our local value. |
44 | pool.install(|| { |
45 | assert!(LOCAL.is_set()); |
46 | LOCAL.with(|y| { |
47 | assert_eq!(x, y); |
48 | }); |
49 | }); |
50 | |
51 | // If we change our local value, the pool is not affected. |
52 | LOCAL.set(&Local(-1), || { |
53 | pool.install(|| { |
54 | assert!(LOCAL.is_set()); |
55 | LOCAL.with(|y| { |
56 | assert_eq!(x, y); |
57 | }); |
58 | }); |
59 | }); |
60 | }) |
61 | .expect("scope threads ok" ); |
62 | // `thread::scope` will wait for the threads to exit before returning. |
63 | }); |
64 | }); |
65 | } |
66 | |
67 | #[test] |
68 | #[cfg_attr (any(target_os = "emscripten" , target_family = "wasm" ), ignore)] |
69 | fn build_scoped_tls_threadpool() { |
70 | LOCAL.set(&Local(42), || { |
71 | LOCAL.with(|x| { |
72 | ThreadPoolBuilder::new() |
73 | .build_scoped( |
74 | move |thread| LOCAL.set(x, || thread.run()), |
75 | |pool| { |
76 | // The pool matches our local value. |
77 | pool.install(|| { |
78 | assert!(LOCAL.is_set()); |
79 | LOCAL.with(|y| { |
80 | assert_eq!(x, y); |
81 | }); |
82 | }); |
83 | |
84 | // If we change our local value, the pool is not affected. |
85 | LOCAL.set(&Local(-1), || { |
86 | pool.install(|| { |
87 | assert!(LOCAL.is_set()); |
88 | LOCAL.with(|y| { |
89 | assert_eq!(x, y); |
90 | }); |
91 | }); |
92 | }); |
93 | }, |
94 | ) |
95 | .expect("thread pool created" ); |
96 | // Internally, `std::thread::scope` will wait for the threads to exit before returning. |
97 | }); |
98 | }); |
99 | } |
100 | |