Skip to main content

pagers_core/
par.rs

1pub(crate) trait SeenInodes {
2    fn already_seen(&self, key: (u64, u64)) -> bool;
3}
4
5#[cfg(feature = "rayon")]
6mod rayon_impl {
7    use std::num::NonZeroU16;
8
9    #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11    pub enum Threads {
12        #[default]
13        All,
14        Exact(NonZeroU16),
15    }
16
17    impl From<u16> for Threads {
18        fn from(n: u16) -> Self {
19            match NonZeroU16::new(n) {
20                None => Self::All,
21                Some(n) => Self::Exact(n),
22            }
23        }
24    }
25
26    impl std::fmt::Display for Threads {
27        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28            match self {
29                Self::All => f.write_str("0"),
30                Self::Exact(n) => write!(f, "{n}"),
31            }
32        }
33    }
34
35    impl std::str::FromStr for Threads {
36        type Err = std::num::ParseIntError;
37
38        fn from_str(s: &str) -> Result<Self, Self::Err> {
39            let n: u16 = s.parse()?;
40            Ok(Self::from(n))
41        }
42    }
43
44    impl Threads {
45        pub fn num_threads(self) -> usize {
46            match self {
47                Self::All => 0,
48                Self::Exact(n) => n.get() as usize,
49            }
50        }
51    }
52
53    impl super::SeenInodes for dashmap::DashMap<(u64, u64), ()> {
54        fn already_seen(&self, key: (u64, u64)) -> bool {
55            self.insert(key, ()).is_some()
56        }
57    }
58
59    pub(crate) type InodeSet = dashmap::DashMap<(u64, u64), ()>;
60}
61
62#[cfg(feature = "rayon")]
63pub(crate) use rayon_impl::InodeSet;
64#[cfg(feature = "rayon")]
65pub use rayon_impl::Threads;
66
67#[cfg(not(feature = "rayon"))]
68impl SeenInodes for std::cell::RefCell<std::collections::HashSet<(u64, u64)>> {
69    fn already_seen(&self, key: (u64, u64)) -> bool {
70        !self.borrow_mut().insert(key)
71    }
72}
73
74#[cfg(not(feature = "rayon"))]
75pub(crate) type InodeSet = std::cell::RefCell<std::collections::HashSet<(u64, u64)>>;
76
77#[cfg(test)]
78#[cfg(feature = "rayon")]
79mod tests {
80    use std::num::NonZeroU16;
81
82    use super::*;
83
84    fn exact(n: u16) -> Threads {
85        Threads::Exact(NonZeroU16::new(n).unwrap())
86    }
87
88    #[test]
89    fn threads_from_zero_is_all() {
90        assert_eq!(Threads::from(0), Threads::All);
91    }
92
93    #[test]
94    fn threads_from_nonzero_is_exact() {
95        assert_eq!(Threads::from(4), exact(4));
96        assert_eq!(Threads::from(1), exact(1));
97    }
98
99    #[test]
100    fn threads_default_is_all() {
101        assert_eq!(Threads::default(), Threads::All);
102    }
103
104    #[test]
105    fn threads_num_threads_all_is_zero() {
106        assert_eq!(Threads::All.num_threads(), 0);
107    }
108
109    #[test]
110    fn threads_num_threads_exact() {
111        assert_eq!(exact(8).num_threads(), 8);
112        assert_eq!(exact(1).num_threads(), 1);
113    }
114
115    #[test]
116    fn threads_display() {
117        assert_eq!(Threads::All.to_string(), "0");
118        assert_eq!(exact(4).to_string(), "4");
119    }
120
121    #[test]
122    fn threads_from_str() {
123        assert_eq!("0".parse::<Threads>(), Ok(Threads::All));
124        assert_eq!("4".parse::<Threads>(), Ok(exact(4)));
125        assert_eq!("1".parse::<Threads>(), Ok(exact(1)));
126        assert!("abc".parse::<Threads>().is_err());
127    }
128
129    #[test]
130    fn threads_display_roundtrip() {
131        for t in [Threads::All, exact(1), exact(8)] {
132            assert_eq!(t.to_string().parse::<Threads>(), Ok(t));
133        }
134    }
135}