summaryrefslogtreecommitdiffstats
path: root/third_party/rust/rayon-core/tests/scoped_threadpool.rs
blob: db3d0b87431d8664e73c6110b1e79a4947da63c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crossbeam_utils::thread;
use rayon_core::ThreadPoolBuilder;

#[derive(PartialEq, Eq, Debug)]
struct Local(i32);

scoped_tls::scoped_thread_local!(static LOCAL: Local);

#[test]
fn missing_scoped_tls() {
    LOCAL.set(&Local(42), || {
        let pool = ThreadPoolBuilder::new()
            .build()
            .expect("thread pool created");

        // `LOCAL` is not set in the pool.
        pool.install(|| {
            assert!(!LOCAL.is_set());
        });
    });
}

#[test]
fn spawn_scoped_tls_threadpool() {
    LOCAL.set(&Local(42), || {
        LOCAL.with(|x| {
            thread::scope(|scope| {
                let pool = ThreadPoolBuilder::new()
                    .spawn_handler(move |thread| {
                        scope
                            .builder()
                            .spawn(move |_| {
                                // Borrow the same local value in the thread pool.
                                LOCAL.set(x, || thread.run())
                            })
                            .map(|_| ())
                    })
                    .build()
                    .expect("thread pool created");

                // The pool matches our local value.
                pool.install(|| {
                    assert!(LOCAL.is_set());
                    LOCAL.with(|y| {
                        assert_eq!(x, y);
                    });
                });

                // If we change our local value, the pool is not affected.
                LOCAL.set(&Local(-1), || {
                    pool.install(|| {
                        assert!(LOCAL.is_set());
                        LOCAL.with(|y| {
                            assert_eq!(x, y);
                        });
                    });
                });
            })
            .expect("scope threads ok");
            // `thread::scope` will wait for the threads to exit before returning.
        });
    });
}

#[test]
fn build_scoped_tls_threadpool() {
    LOCAL.set(&Local(42), || {
        LOCAL.with(|x| {
            ThreadPoolBuilder::new()
                .build_scoped(
                    move |thread| LOCAL.set(x, || thread.run()),
                    |pool| {
                        // The pool matches our local value.
                        pool.install(|| {
                            assert!(LOCAL.is_set());
                            LOCAL.with(|y| {
                                assert_eq!(x, y);
                            });
                        });

                        // If we change our local value, the pool is not affected.
                        LOCAL.set(&Local(-1), || {
                            pool.install(|| {
                                assert!(LOCAL.is_set());
                                LOCAL.with(|y| {
                                    assert_eq!(x, y);
                                });
                            });
                        });
                    },
                )
                .expect("thread pool created");
            // Internally, `crossbeam::scope` will wait for the threads to exit before returning.
        });
    });
}