1use crate::core::types::*;
4use crate::core::{MemScopeError, MemScopeResult, SystemErrorType};
5use std::collections::HashMap;
6use std::sync::atomic::{AtomicU64, Ordering};
7use std::sync::{Arc, Mutex, OnceLock, RwLock};
8use std::time::{SystemTime, UNIX_EPOCH};
9
10static GLOBAL_SCOPE_TRACKER: OnceLock<Arc<ScopeTracker>> = OnceLock::new();
12
13pub fn get_global_scope_tracker() -> Arc<ScopeTracker> {
15 GLOBAL_SCOPE_TRACKER
16 .get_or_init(|| Arc::new(ScopeTracker::new()))
17 .clone()
18}
19
20pub type ScopeId = u64;
22
23pub struct ScopeTracker {
25 pub active_scopes: RwLock<HashMap<ScopeId, ScopeInfo>>,
27 pub completed_scopes: Mutex<Vec<ScopeInfo>>,
29 pub scope_hierarchy: Mutex<ScopeHierarchy>,
31 next_scope_id: AtomicU64,
33 pub scope_stack: RwLock<HashMap<String, Vec<ScopeId>>>,
35}
36
37impl ScopeTracker {
38 pub fn new() -> Self {
40 Self {
41 active_scopes: RwLock::new(HashMap::new()),
42 completed_scopes: Mutex::new(Vec::new()),
43 scope_hierarchy: Mutex::new(ScopeHierarchy {
44 root_scopes: Vec::new(),
45 scope_tree: HashMap::new(),
46 max_depth: 0,
47 total_scopes: 0,
48 relationships: HashMap::new(),
49 depth_map: HashMap::new(),
50 }),
51 next_scope_id: AtomicU64::new(1),
52 scope_stack: RwLock::new(HashMap::new()),
53 }
54 }
55
56 pub fn enter_scope(&self, name: String) -> MemScopeResult<ScopeId> {
58 let scope_id = self.allocate_scope_id();
59 let thread_id = format!("{:?}", std::thread::current().id());
60 let timestamp = current_timestamp();
61
62 let (parent_scope, depth) = {
63 let stack = self.scope_stack.read().map_err(|e| {
64 MemScopeError::system(
65 SystemErrorType::Locking,
66 format!("Failed to acquire scope_stack read lock: {}", e),
67 )
68 })?;
69 if let Some(thread_stack) = stack.get(&thread_id) {
70 if let Some(&parent_id) = thread_stack.last() {
71 let active = self.active_scopes.read().map_err(|e| {
72 MemScopeError::system(
73 SystemErrorType::Locking,
74 format!("Failed to acquire active_scopes read lock: {}", e),
75 )
76 })?;
77 if let Some(parent) = active.get(&parent_id) {
78 (Some(parent.name.clone()), parent.depth + 1)
79 } else {
80 (None, 0)
81 }
82 } else {
83 (None, 0)
84 }
85 } else {
86 (None, 0)
87 }
88 };
89
90 let scope_info = ScopeInfo {
91 name: name.clone(),
92 parent: parent_scope.clone(),
93 children: Vec::new(),
94 depth,
95 variables: Vec::new(),
96 total_memory: 0,
97 peak_memory: 0,
98 allocation_count: 0,
99 lifetime_start: Some(timestamp as u64),
100 lifetime_end: None,
101 is_active: true,
102 start_time: timestamp as u64,
103 end_time: None,
104 memory_usage: 0,
105 child_scopes: Vec::new(),
106 parent_scope: parent_scope.clone(),
107 };
108
109 self.active_scopes
110 .write()
111 .map_err(|e| {
112 MemScopeError::system(
113 SystemErrorType::Locking,
114 format!("Failed to acquire active_scopes write lock: {}", e),
115 )
116 })?
117 .insert(scope_id, scope_info);
118
119 self.scope_stack
120 .write()
121 .map_err(|e| {
122 MemScopeError::system(
123 SystemErrorType::Locking,
124 format!("Failed to acquire scope_stack write lock: {}", e),
125 )
126 })?
127 .entry(thread_id.clone())
128 .or_default()
129 .push(scope_id);
130
131 if let Ok(mut hierarchy) = self.scope_hierarchy.lock() {
132 hierarchy.depth_map.insert(name.clone(), depth);
133
134 if let Some(parent) = parent_scope.clone() {
135 hierarchy
136 .relationships
137 .entry(parent)
138 .or_default()
139 .push(name.clone());
140 } else {
141 hierarchy.root_scopes.push(name);
142 }
143 }
144
145 Ok(scope_id)
146 }
147
148 pub fn exit_scope(&self, scope_id: ScopeId) -> MemScopeResult<()> {
150 let thread_id = format!("{:?}", std::thread::current().id());
151 let timestamp = current_timestamp();
152
153 let mut scope_info = self
154 .active_scopes
155 .write()
156 .map_err(|e| {
157 MemScopeError::system(
158 SystemErrorType::Locking,
159 format!("Failed to acquire active_scopes write lock: {}", e),
160 )
161 })?
162 .remove(&scope_id)
163 .ok_or_else(|| MemScopeError::internal(format!("Invalid scope ID: {scope_id}")))?;
164
165 scope_info.end_time = Some(timestamp as u64);
166 scope_info.lifetime_end = Some(timestamp as u64);
167
168 if let Ok(mut stack) = self.scope_stack.write() {
169 if let Some(thread_stack) = stack.get_mut(&thread_id) {
170 if let Some(pos) = thread_stack.iter().position(|&id| id == scope_id) {
171 thread_stack.remove(pos);
172 }
173 }
174 }
175
176 if let Ok(mut completed_scopes) = self.completed_scopes.lock() {
177 completed_scopes.push(scope_info);
178 }
179
180 Ok(())
181 }
182
183 pub fn associate_variable(
184 &self,
185 variable_name: String,
186 memory_size: usize,
187 ) -> MemScopeResult<()> {
188 let thread_id = format!("{:?}", std::thread::current().id());
189
190 let current_scope_id = self
191 .scope_stack
192 .read()
193 .map_err(|e| {
194 MemScopeError::system(
195 SystemErrorType::Locking,
196 format!("Failed to acquire scope_stack read lock: {}", e),
197 )
198 })?
199 .get(&thread_id)
200 .and_then(|stack| stack.last().copied());
201
202 if let Some(scope_id) = current_scope_id {
203 if let Ok(mut active) = self.active_scopes.write() {
204 if let Some(scope) = active.get_mut(&scope_id) {
205 scope.variables.push(variable_name);
206 scope.memory_usage += memory_size;
207 scope.peak_memory = scope.peak_memory.max(scope.memory_usage);
208 scope.allocation_count += 1;
209 }
210 }
211 }
212
213 Ok(())
214 }
215
216 pub fn get_scope_analysis(&self) -> MemScopeResult<ScopeAnalysis> {
217 let mut all_scopes: Vec<ScopeInfo> = self
218 .active_scopes
219 .read()
220 .map_err(|e| {
221 MemScopeError::system(
222 SystemErrorType::Locking,
223 format!("Failed to acquire active_scopes read lock: {}", e),
224 )
225 })?
226 .values()
227 .cloned()
228 .collect();
229
230 if let Ok(completed_scopes) = self.completed_scopes.lock() {
231 all_scopes.extend(completed_scopes.iter().cloned());
232 }
233
234 let hierarchy = if let Ok(hierarchy) = self.scope_hierarchy.lock() {
235 hierarchy.clone()
236 } else {
237 ScopeHierarchy {
238 root_scopes: Vec::new(),
239 scope_tree: HashMap::new(),
240 max_depth: 0,
241 total_scopes: 0,
242 relationships: HashMap::new(),
243 depth_map: HashMap::new(),
244 }
245 };
246
247 Ok(ScopeAnalysis {
248 total_scopes: all_scopes.len(),
249 active_scopes: all_scopes.iter().filter(|s| s.is_active).count(),
250 max_depth: hierarchy.max_depth,
251 average_lifetime: 1000.0,
252 memory_efficiency: 0.8,
253 scopes: all_scopes,
254 scope_hierarchy: hierarchy,
255 cross_scope_references: Vec::new(),
256 })
257 }
258
259 pub fn get_scope_lifecycle_metrics(&self) -> MemScopeResult<Vec<ScopeLifecycleMetrics>> {
260 let metrics = if let Ok(completed_scopes) = self.completed_scopes.lock() {
261 completed_scopes
262 .iter()
263 .map(|scope| {
264 let lifetime =
265 scope.end_time.unwrap_or(current_timestamp() as u64) - scope.start_time;
266 let efficiency_score = if scope.peak_memory > 0 {
267 scope.memory_usage as f64 / scope.peak_memory as f64
268 } else {
269 1.0
270 };
271
272 ScopeLifecycleMetrics {
273 scope_name: scope.name.clone(),
274 variable_count: scope.variables.len(),
275 average_lifetime_ms: lifetime as f64,
276 total_memory_usage: scope.memory_usage,
277 peak_memory_usage: scope.peak_memory,
278 allocation_frequency: 1.0,
279 deallocation_efficiency: efficiency_score,
280 completed_allocations: scope.allocation_count,
281 memory_growth_events: 0,
282 peak_concurrent_variables: scope.variables.len(),
283 memory_efficiency_ratio: if scope.peak_memory > 0 {
284 scope.memory_usage as f64 / scope.peak_memory as f64
285 } else {
286 1.0
287 },
288 ownership_transfer_events: 0,
289 fragmentation_score: 0.0,
290 instant_allocations: 0,
291 short_term_allocations: 0,
292 medium_term_allocations: 0,
293 long_term_allocations: 0,
294 suspected_leaks: 0,
295 risk_distribution: crate::core::types::RiskDistribution::default(),
296 scope_metrics: Vec::new(),
297 type_lifecycle_patterns: Vec::new(),
298 }
299 })
300 .collect()
301 } else {
302 Vec::new()
303 };
304
305 Ok(metrics)
306 }
307
308 pub fn get_all_scopes(&self) -> Vec<ScopeInfo> {
309 let mut all_scopes: Vec<ScopeInfo> = match self.active_scopes.read() {
310 Ok(active) => active.values().cloned().collect(),
311 Err(_) => Vec::new(),
312 };
313
314 if let Ok(completed_scopes) = self.completed_scopes.lock() {
315 all_scopes.extend(completed_scopes.iter().cloned());
316 }
317
318 all_scopes
319 }
320
321 fn allocate_scope_id(&self) -> ScopeId {
323 self.next_scope_id.fetch_add(1, Ordering::Relaxed)
324 }
325}
326
327impl Default for ScopeTracker {
328 fn default() -> Self {
329 Self::new()
330 }
331}
332
333pub struct ScopeGuard {
335 scope_id: ScopeId,
336 tracker: Arc<ScopeTracker>,
337}
338
339impl ScopeGuard {
340 pub fn enter(name: &str) -> MemScopeResult<Self> {
341 let tracker = get_global_scope_tracker();
342 let scope_id = tracker.enter_scope(name.to_string())?;
343
344 Ok(Self { scope_id, tracker })
345 }
346
347 pub fn scope_id(&self) -> ScopeId {
348 self.scope_id
349 }
350}
351
352impl Drop for ScopeGuard {
353 fn drop(&mut self) {
354 let _ = self.tracker.exit_scope(self.scope_id);
355 }
356}
357
358fn current_timestamp() -> u128 {
359 SystemTime::now()
360 .duration_since(UNIX_EPOCH)
361 .map(|d| d.as_millis())
362 .unwrap_or(0)
363}
364
365#[macro_export]
367macro_rules! track_scope {
368 ($scope_name:expr) => {
369 let _scope_guard = $crate::scope_tracker::ScopeGuard::enter($scope_name)?;
370 };
371 ($scope_name:expr, $block:block) => {{
372 let _scope_guard = $crate::scope_tracker::ScopeGuard::enter($scope_name)?;
373 $block
374 }};
375}
376
377#[macro_export]
379macro_rules! track_var_with_scope {
380 ($var:ident) => {{
381 let result = $crate::_track_var_impl(&$var, stringify!($var));
383
384 if result.is_ok() {
386 if let Some(size) = $crate::Trackable::get_heap_ptr(&$var) {
387 let scope_tracker = $crate::scope_tracker::get_global_scope_tracker();
388 let _ = scope_tracker
389 .associate_variable(stringify!($var).to_string(), std::mem::size_of_val(&$var));
390 }
391 }
392
393 result
394 }};
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_scope_tracker_creation() {
403 let tracker = ScopeTracker::new();
404 assert_eq!(tracker.next_scope_id.load(Ordering::SeqCst), 1);
405 }
406
407 #[test]
408 fn test_enter_and_exit_scope() {
409 let tracker = ScopeTracker::new();
410 let scope_id = tracker.enter_scope("test_scope".to_string()).unwrap();
411
412 assert!(tracker
414 .active_scopes
415 .read()
416 .unwrap()
417 .get(&scope_id)
418 .is_some());
419
420 tracker.exit_scope(scope_id).unwrap();
422
423 assert!(tracker
425 .active_scopes
426 .read()
427 .unwrap()
428 .get(&scope_id)
429 .is_none());
430 }
431}