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.get_mut().expect("Mutex was poisoned");
28
29        GetSizeTracker::track(&mut *tracker, addr)
30    }
31}
32
33impl<T: GetSizeTracker> GetSizeTracker for RwLock<T> {
34    fn track<A>(&mut self, addr: *const A) -> bool {
35        let mut tracker = self.write().expect("RwLock was poisoned");
36
37        GetSizeTracker::track(&mut *tracker, addr)
38    }
39}
40
41impl<T: GetSizeTracker> GetSizeTracker for Arc<Mutex<T>> {
42    fn track<A>(&mut self, addr: *const A) -> bool {
43        let mut tracker = self.lock().expect("Mutex was poisoned");
44
45        GetSizeTracker::track(&mut *tracker, addr)
46    }
47}
48
49impl<T: GetSizeTracker> GetSizeTracker for Arc<RwLock<T>> {
50    fn track<A>(&mut self, addr: *const A) -> bool {
51        let mut tracker = self.write().expect("RwLock was poisoned");
52
53        GetSizeTracker::track(&mut *tracker, addr)
54    }
55}
56
57/// A simple standard tracker which can be used to track shared ownership references.
58#[derive(Debug, Default)]
59pub struct StandardTracker {
60    inner: HashSet<usize>,
61}
62
63impl StandardTracker {
64    #[must_use]
65    pub fn new() -> Self {
66        Self::default()
67    }
68
69    pub fn clear(&mut self) {
70        self.inner.clear();
71    }
72}
73
74impl GetSizeTracker for StandardTracker {
75    fn track<A>(&mut self, addr: *const A) -> bool {
76        self.inner.insert(addr.addr())
77    }
78}
79
80/// A pseudo tracker which does not track anything.
81#[derive(Debug, Clone, Copy, Default)]
82pub struct NoTracker {
83    answer: bool,
84}
85
86impl NoTracker {
87    /// Creates a new pseudo tracker, which will always return the given `answer`.
88    #[must_use]
89    pub const fn new(answer: bool) -> Self {
90        Self { answer }
91    }
92
93    /// Get the answer which will always be returned by this pseudo tracker.
94    #[must_use]
95    pub const fn answer(&self) -> bool {
96        self.answer
97    }
98
99    /// Changes the answer which will always be returned by this pseudo tracker.
100    pub fn set_answer(&mut self, answer: bool) {
101        self.answer = answer;
102    }
103}
104
105impl GetSizeTracker for NoTracker {
106    fn track<A>(&mut self, _addr: *const A) -> bool {
107        self.answer
108    }
109}