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