Skip to main content

get_size2/
tracker.rs

1use std::collections::HashSet;
2use std::sync::{Arc, Mutex, RwLock};
3
4/// A tracker which makes sure that shared ownership objects are only accounted for once.
5pub trait GetSizeTracker {
6    /// Tracks an arbitrary object located at `addr`.
7    ///
8    /// Returns `true` if the reference, as indexed by the pointed to `addr`, has not yet
9    /// been seen by this tracker. Otherwise it returns `false`.
10    fn track<A>(&mut self, addr: *const A) -> bool;
11}
12
13impl<T: GetSizeTracker> GetSizeTracker for &mut T {
14    fn track<A>(&mut self, addr: *const A) -> bool {
15        GetSizeTracker::track(*self, addr)
16    }
17}
18
19impl<T: GetSizeTracker> GetSizeTracker for Box<T> {
20    fn track<A>(&mut self, addr: *const A) -> bool {
21        GetSizeTracker::track(&mut **self, addr)
22    }
23}
24
25impl<T: GetSizeTracker> GetSizeTracker for Mutex<T> {
26    fn track<A>(&mut self, addr: *const A) -> bool {
27        let tracker = self
28            .get_mut()
29            .unwrap_or_else(std::sync::PoisonError::into_inner);
30
31        GetSizeTracker::track(&mut *tracker, addr)
32    }
33}
34
35impl<T: GetSizeTracker> GetSizeTracker for RwLock<T> {
36    fn track<A>(&mut self, addr: *const A) -> bool {
37        let mut tracker = self
38            .write()
39            .unwrap_or_else(std::sync::PoisonError::into_inner);
40
41        GetSizeTracker::track(&mut *tracker, addr)
42    }
43}
44
45impl<T: GetSizeTracker> GetSizeTracker for Arc<Mutex<T>> {
46    fn track<A>(&mut self, addr: *const A) -> bool {
47        let mut tracker = self
48            .lock()
49            .unwrap_or_else(std::sync::PoisonError::into_inner);
50
51        GetSizeTracker::track(&mut *tracker, addr)
52    }
53}
54
55impl<T: GetSizeTracker> GetSizeTracker for Arc<RwLock<T>> {
56    fn track<A>(&mut self, addr: *const A) -> bool {
57        let mut tracker = self
58            .write()
59            .unwrap_or_else(std::sync::PoisonError::into_inner);
60
61        GetSizeTracker::track(&mut *tracker, addr)
62    }
63}
64
65/// A simple standard tracker which can be used to track shared ownership references.
66#[derive(Debug, Default)]
67pub struct StandardTracker {
68    inner: HashSet<usize>,
69}
70
71impl StandardTracker {
72    #[must_use]
73    pub fn new() -> Self {
74        Self::default()
75    }
76
77    pub fn clear(&mut self) {
78        self.inner.clear();
79    }
80}
81
82impl GetSizeTracker for StandardTracker {
83    fn track<A>(&mut self, addr: *const A) -> bool {
84        self.inner.insert(addr.addr())
85    }
86}
87
88/// A pseudo tracker which does not track anything.
89#[derive(Debug, Clone, Copy, Default)]
90pub struct NoTracker {
91    answer: bool,
92}
93
94impl NoTracker {
95    /// Creates a new pseudo tracker, which will always return the given `answer`.
96    #[must_use]
97    pub const fn new(answer: bool) -> Self {
98        Self { answer }
99    }
100
101    /// Get the answer which will always be returned by this pseudo tracker.
102    #[must_use]
103    pub const fn answer(&self) -> bool {
104        self.answer
105    }
106
107    /// Changes the answer which will always be returned by this pseudo tracker.
108    pub const fn set_answer(&mut self, answer: bool) {
109        self.answer = answer;
110    }
111}
112
113impl GetSizeTracker for NoTracker {
114    fn track<A>(&mut self, _addr: *const A) -> bool {
115        self.answer
116    }
117}