• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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