loupe/memory_usage/
sync.rs1#[cfg(test)]
2use crate::{assert_size_of_val_eq, POINTER_BYTE_SIZE};
3use crate::{MemoryUsage, MemoryUsageTracker};
4use std::mem;
5use std::sync::{
6 atomic::{
7 AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
8 AtomicU64, AtomicU8, AtomicUsize,
9 },
10 Arc, Mutex, RwLock, Weak,
11};
12
13macro_rules! impl_memory_usage_for_numeric {
14 ( $type:ty ) => {
15 impl MemoryUsage for $type {
16 fn size_of_val(&self, _: &mut dyn MemoryUsageTracker) -> usize {
17 mem::size_of_val(self)
18 }
19 }
20 };
21
22 ( $( $type:ty ),+ $(,)* ) => {
23 $( impl_memory_usage_for_numeric!( $type ); )+
24 }
25}
26
27impl_memory_usage_for_numeric!(
28 AtomicBool,
29 AtomicI8,
30 AtomicI16,
31 AtomicI32,
32 AtomicI64,
33 AtomicIsize,
34 AtomicU8,
35 AtomicU16,
36 AtomicU32,
37 AtomicU64,
38 AtomicUsize,
39);
40
41impl<T> MemoryUsage for Arc<T>
42where
43 T: MemoryUsage + ?Sized,
44{
45 fn size_of_val(&self, tracker: &mut dyn MemoryUsageTracker) -> usize {
46 mem::size_of_val(self)
47 + if tracker.track(Arc::as_ptr(self) as *const ()) {
48 self.as_ref().size_of_val(tracker)
49 } else {
50 0
51 }
52 }
53}
54
55impl<T> MemoryUsage for Weak<T>
56where
57 T: MemoryUsage + ?Sized,
58{
59 fn size_of_val(&self, tracker: &mut dyn MemoryUsageTracker) -> usize {
60 mem::size_of_val(self)
61 + if tracker.track(Weak::as_ptr(self) as *const ()) {
62 Weak::upgrade(self)
63 .map(|arc| arc.as_ref().size_of_val(tracker))
64 .unwrap_or(0)
65 } else {
66 0
67 }
68 }
69}
70
71impl<T> MemoryUsage for Mutex<T>
72where
73 T: MemoryUsage + ?Sized,
74{
75 fn size_of_val(&self, tracker: &mut dyn MemoryUsageTracker) -> usize {
76 mem::size_of_val(self) + self.lock().unwrap().size_of_val(tracker)
77 }
78}
79
80impl<T> MemoryUsage for RwLock<T>
81where
82 T: MemoryUsage + ?Sized,
83{
84 fn size_of_val(&self, tracker: &mut dyn MemoryUsageTracker) -> usize {
85 mem::size_of_val(self) + self.read().unwrap().size_of_val(tracker)
86 }
87}
88
89#[cfg(test)]
90mod test_sync_types {
91 use super::*;
92
93 macro_rules! test_memory_usage_for_numeric {
94 ($test_name:ident: ($value:expr) == $expected:expr) => {
95 #[test]
96 fn $test_name() {
97 assert_size_of_val_eq!($value, $expected);
98 }
99 };
100
101 ( $( $test_name:ident: ($value:expr) == $expected:expr );+ $(;)* ) => {
102 $( test_memory_usage_for_numeric!( $test_name: ($value) == $expected); )+
103 }
104 }
105
106 test_memory_usage_for_numeric!(
107 test_atomic_bool: (AtomicBool::new(true)) == 1;
108 test_atomic_i8: (AtomicI8::new(1i8)) == 1;
109 test_atomic_i16: (AtomicI16::new(1i16)) == 2;
110 test_atomic_i32: (AtomicI32::new(1i32)) == 4;
111 test_atomic_i64: (AtomicI64::new(1i64)) == 8;
112 test_atomic_isize: (AtomicIsize::new(1isize)) == POINTER_BYTE_SIZE;
113 test_atomic_u8: (AtomicU8::new(1u8)) == 1;
114 test_atomic_u16: (AtomicU16::new(1u16)) == 2;
115 test_atomic_u32: (AtomicU32::new(1u32)) == 4;
116 test_atomic_u64: (AtomicU64::new(1u64)) == 8;
117 test_atomic_usize: (AtomicUsize::new(1usize)) == POINTER_BYTE_SIZE;
118 );
119
120 #[test]
121 fn test_arc() {
122 let empty_arc_size = mem::size_of_val(&Arc::new(()));
123
124 let arc: Arc<i32> = Arc::new(1);
125 assert_size_of_val_eq!(arc, empty_arc_size + 4);
126
127 let arc: Arc<Option<i32>> = Arc::new(Some(1));
128 assert_size_of_val_eq!(arc, empty_arc_size + POINTER_BYTE_SIZE + 4);
129 }
130
131 #[test]
132 fn test_weak() {
133 let empty_weak_size = mem::size_of_val(&Arc::downgrade(&Arc::new(())));
134
135 let arc: Arc<i32> = Arc::new(1);
136 let weak: Weak<i32> = Arc::downgrade(&arc);
137 assert_size_of_val_eq!(weak, empty_weak_size + 4);
138
139 let arc: Arc<Option<i32>> = Arc::new(Some(1));
140 let weak: Weak<Option<i32>> = Arc::downgrade(&arc);
141 assert_size_of_val_eq!(weak, empty_weak_size + POINTER_BYTE_SIZE + 4);
142
143 let weak: Weak<i32> = {
144 let arc: Arc<i32> = Arc::new(5);
145 Arc::downgrade(&arc)
146 };
147 assert_size_of_val_eq!(weak, empty_weak_size);
148 }
149
150 #[test]
151 fn test_mutex() {
152 let empty_mutex_size = mem::size_of_val(&Mutex::new(()));
153
154 let mutex: Mutex<i32> = Mutex::new(1);
155 assert_size_of_val_eq!(mutex, empty_mutex_size + 4);
156
157 let mutex: Mutex<Option<i32>> = Mutex::new(Some(1));
158 assert_size_of_val_eq!(mutex, empty_mutex_size + 2 * POINTER_BYTE_SIZE + 4);
159 }
160
161 #[test]
162 fn test_rwlock() {
163 let empty_rwlock_size = mem::size_of_val(&RwLock::new(()));
164
165 let rwlock: RwLock<i32> = RwLock::new(1);
166 assert_size_of_val_eq!(rwlock, empty_rwlock_size + 4);
167
168 let rwlock: RwLock<Option<i32>> = RwLock::new(Some(1));
169 assert_size_of_val_eq!(rwlock, empty_rwlock_size + 2 * POINTER_BYTE_SIZE + 4);
170 }
171}