1use crossbeam_utils::thread;
2use rayon_core::ThreadPoolBuilder;
3
4#[derive(PartialEq, Eq, Debug)]
5struct Local(i32);
6
7scoped_tls::scoped_thread_local!(static LOCAL: Local);
8
9#[test]
10#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)]
11fn 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)]
26fn 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)]
69fn 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