csv_diff/
thread_scope_strategy.rs

1#[cfg(feature = "rayon-threads")]
2use mown::Mown;
3
4pub trait ThreadScoper<S> {
5    fn scope<F>(&self, f: F)
6    where
7        F: FnOnce(&S) + Send;
8}
9#[derive(Debug, Default)]
10#[cfg(feature = "crossbeam-threads")]
11pub struct CrossbeamScope;
12
13#[cfg(feature = "crossbeam-threads")]
14impl<'scope> ThreadScoper<crossbeam_utils::thread::Scope<'scope>> for CrossbeamScope {
15    fn scope<F>(&self, f: F)
16    where
17        F: FnOnce(&crossbeam_utils::thread::Scope<'scope>),
18    {
19        crossbeam_utils::thread::scope(|s| f(s)).unwrap();
20    }
21}
22
23#[cfg(feature = "crossbeam-threads")]
24impl CrossbeamScope {
25    pub fn new() -> Self {
26        Self
27    }
28}
29
30#[derive(Debug)]
31#[cfg(feature = "rayon-threads")]
32pub struct RayonScope<'tp> {
33    thread_pool: Mown<'tp, rayon::ThreadPool>,
34}
35
36#[cfg(feature = "rayon-threads")]
37impl<'scope> ThreadScoper<rayon::Scope<'scope>> for RayonScope<'_> {
38    fn scope<F>(&self, f: F)
39    where
40        F: FnOnce(&rayon::Scope<'scope>) + Send,
41    {
42        self.thread_pool.scope(|s| f(s));
43    }
44}
45
46#[cfg(feature = "rayon-threads")]
47impl<'tp> RayonScope<'tp> {
48    pub fn with_thread_pool_ref(thread_pool: &'tp rayon::ThreadPool) -> Self {
49        Self {
50            thread_pool: Mown::Borrowed(thread_pool),
51        }
52    }
53
54    pub fn with_thread_pool_owned(thread_pool: rayon::ThreadPool) -> Self {
55        Self {
56            thread_pool: Mown::Owned(thread_pool),
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use std::sync::atomic::{AtomicU64, Ordering};
64
65    #[cfg(feature = "crossbeam-threads")]
66    use super::CrossbeamScope;
67    #[cfg(feature = "rayon-threads")]
68    use super::RayonScope;
69    use super::ThreadScoper;
70    #[test]
71    #[cfg(feature = "crossbeam-threads")]
72    fn crossbeam_scope_add_num() {
73        let num = AtomicU64::new(0);
74        let crossbeam_scope = CrossbeamScope::new();
75        crossbeam_scope.scope(|s| {
76            s.spawn(|_s1| {
77                num.fetch_add(1, Ordering::SeqCst);
78            });
79            s.spawn(|_s2| {
80                num.fetch_add(1, Ordering::SeqCst);
81            });
82        });
83        assert_eq!(2, num.into_inner());
84    }
85
86    #[test]
87    #[cfg(feature = "rayon-threads")]
88    fn rayon_scope_add_num() {
89        let num = AtomicU64::new(0);
90        let tp = rayon::ThreadPoolBuilder::new().build().unwrap();
91        let rayon_scope = RayonScope::with_thread_pool_ref(&tp);
92        rayon_scope.scope(|s| {
93            s.spawn(|_s1| {
94                num.fetch_add(1, Ordering::SeqCst);
95            });
96            s.spawn(|_s2| {
97                num.fetch_add(1, Ordering::SeqCst);
98            });
99        });
100        assert_eq!(2, num.into_inner());
101    }
102}