memscope_rs/capture/backends/async_tracker/
dealloc.rs1use super::*;
7
8impl AsyncTracker {
9 pub fn track_deallocation(&self, ptr: usize) {
16 self.close_allocation(ptr, None, None);
17 }
18
19 pub fn track_deallocation_matching(
25 &self,
26 ptr: usize,
27 size: Option<usize>,
28 generation: Option<u64>,
29 ) {
30 self.close_allocation(ptr, size, generation);
31 }
32
33 fn close_allocation(&self, ptr: usize, size: Option<usize>, generation: Option<u64>) {
34 let closed = {
35 let Ok(mut allocations) = self.allocations.lock() else {
36 tracing::error!("Failed to acquire allocations lock during track_deallocation");
37 return;
38 };
39 self.close_allocation_inner(&mut allocations, ptr, size, generation)
40 };
41
42 self.apply_deallocation_stats(closed);
43 }
44
45 fn close_allocation_inner(
48 &self,
49 allocations: &mut std::sync::MutexGuard<'_, HashMap<usize, Vec<AsyncAllocation>>>,
50 ptr: usize,
51 size: Option<usize>,
52 generation: Option<u64>,
53 ) -> Option<AsyncAllocation> {
54 let entries = allocations.get_mut(&ptr)?;
55
56 let index = match (generation, size) {
61 (Some(generation), _) => entries.iter().position(|a| a.generation == generation),
62 (None, Some(size)) => entries.iter().position(|a| a.size == size),
63 (None, None) => Some(0),
64 };
65 let Some(index) = index else {
66 tracing::debug!(
67 "unmatched async release: ptr={:#x}, size={:?}, generation={:?}",
68 ptr,
69 size,
70 generation
71 );
72 return None;
73 };
74
75 let closed = entries.remove(index);
76 if entries.is_empty() {
77 allocations.remove(&ptr);
78 }
79 Some(closed)
80 }
81
82 fn apply_deallocation_stats(&self, closed: Option<AsyncAllocation>) {
84 let Some(closed) = closed else {
85 return;
86 };
87 if closed.task_id != 0 {
88 if let Ok(mut profiles) = self.profiles.lock() {
89 if let Some(profile) = profiles.get_mut(&closed.task_id) {
90 profile.record_deallocation(closed.size as u64);
91 }
92 } else {
93 tracing::error!("Failed to acquire profiles lock during track_deallocation");
94 }
95 }
96
97 if closed.size > 0 {
98 if let Ok(mut stats) = self.stats.lock() {
99 stats.active_memory = stats.active_memory.saturating_sub(closed.size);
100 stats.total_deallocations += 1;
101 stats.total_deallocated += closed.size as u64;
102 } else {
103 tracing::error!("Failed to acquire stats lock during track_deallocation");
104 }
105 }
106 }
107}