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)]
missing_scoped_tls()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)]
spawn_scoped_tls_threadpool()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)]
build_scoped_tls_threadpool()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, `crossbeam::scope` will wait for the threads to exit before returning.
97 });
98 });
99 }
100