1use crate::core::safe_operations::SafeLock;
7use parking_lot::Mutex;
8use std::borrow::ToOwned;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::time::{Duration, Instant};
11
12pub enum SmartMutex<T> {
14 Standard(std::sync::Mutex<T>),
16 ParkingLot(parking_lot::Mutex<T>),
18}
19
20impl<T> SmartMutex<T> {
21 pub fn new(data: T) -> Self {
23 SmartMutex::Standard(std::sync::Mutex::new(data))
24 }
25
26 pub fn lock(&self) -> SmartMutexGuard<'_, T> {
28 match self {
29 SmartMutex::Standard(mutex) => {
30 let start = Instant::now();
31 let guard = mutex.safe_lock().expect("Failed to lock standard mutex");
32 let wait_time = start.elapsed();
33
34 if wait_time > Duration::from_micros(100) {
36 record_contention("std_mutex", wait_time);
38 }
39
40 SmartMutexGuard::Standard(guard)
41 }
42 SmartMutex::ParkingLot(mutex) => SmartMutexGuard::ParkingLot(mutex.lock()),
43 }
44 }
45
46 pub fn try_lock(&self) -> Option<SmartMutexGuard<'_, T>> {
48 match self {
49 SmartMutex::Standard(mutex) => mutex.try_lock().ok().map(SmartMutexGuard::Standard),
50 SmartMutex::ParkingLot(mutex) => mutex.try_lock().map(SmartMutexGuard::ParkingLot),
51 }
52 }
53}
54
55pub enum SmartMutexGuard<'a, T> {
56 Standard(std::sync::MutexGuard<'a, T>),
57 ParkingLot(parking_lot::MutexGuard<'a, T>),
58}
59
60impl<'a, T> std::ops::Deref for SmartMutexGuard<'a, T> {
61 type Target = T;
62
63 fn deref(&self) -> &Self::Target {
64 match self {
65 SmartMutexGuard::Standard(guard) => guard,
66 SmartMutexGuard::ParkingLot(guard) => guard,
67 }
68 }
69}
70
71impl<'a, T> std::ops::DerefMut for SmartMutexGuard<'a, T> {
72 fn deref_mut(&mut self) -> &mut Self::Target {
73 match self {
74 SmartMutexGuard::Standard(guard) => guard,
75 SmartMutexGuard::ParkingLot(guard) => guard,
76 }
77 }
78}
79
80static CONTENTION_COUNTER: AtomicU64 = AtomicU64::new(0);
82static TOTAL_WAIT_TIME_NS: AtomicU64 = AtomicU64::new(0);
83
84fn record_contention(mutex_type: &str, wait_time: Duration) {
85 CONTENTION_COUNTER.fetch_add(1, Ordering::Relaxed);
86 TOTAL_WAIT_TIME_NS.fetch_add(wait_time.as_nanos() as u64, Ordering::Relaxed);
87
88 if CONTENTION_COUNTER.load(Ordering::Relaxed) % 1000 == 0 {
90 let avg_wait =
91 TOTAL_WAIT_TIME_NS.load(Ordering::Relaxed) / CONTENTION_COUNTER.load(Ordering::Relaxed);
92 tracing::debug!(
93 "Mutex contention detected: {} avg wait: {}ns",
94 mutex_type,
95 avg_wait
96 );
97 }
98}
99
100pub trait SafeUnwrap<T> {
102 fn safe_unwrap(self, fallback: T) -> T;
104
105 fn safe_unwrap_or_log(self, context: &str, fallback: T) -> T;
107}
108
109impl<T> SafeUnwrap<T> for Option<T> {
110 fn safe_unwrap(self, fallback: T) -> T {
111 match self {
112 Some(value) => value,
113 None => {
114 #[cfg(debug_assertions)]
115 {
116 tracing::warn!("safe_unwrap called on None, using fallback");
117 fallback
118 }
119
120 #[cfg(not(debug_assertions))]
121 {
122 tracing::warn!("safe_unwrap called on None, using fallback");
123 fallback
124 }
125 }
126 }
127 }
128
129 fn safe_unwrap_or_log(self, context: &str, fallback: T) -> T {
130 match self {
131 Some(value) => value,
132 None => {
133 tracing::warn!("safe_unwrap_or_log failed in context: {}", context);
134 fallback
135 }
136 }
137 }
138}
139
140impl<T, E: std::fmt::Debug> SafeUnwrap<T> for Result<T, E> {
141 fn safe_unwrap(self, _fallback: T) -> T {
142 match self {
143 Ok(value) => value,
144 Err(e) => {
145 #[cfg(debug_assertions)]
146 panic!("Called safe_unwrap on Err: {e:?}");
147
148 #[cfg(not(debug_assertions))]
149 {
150 tracing::warn!("safe_unwrap called on Err: {e:?}, using fallback");
151 _fallback
152 }
153 }
154 }
155 }
156
157 fn safe_unwrap_or_log(self, context: &str, fallback: T) -> T {
158 match self {
159 Ok(value) => value,
160 Err(e) => {
161 tracing::warn!(
162 "safe_unwrap_or_log failed in context: {context} - error: {:?}",
163 e
164 );
165 fallback
166 }
167 }
168 }
169}
170
171pub trait SmartClone<T: ?Sized + ToOwned> {
173 fn smart_clone(&self) -> std::borrow::Cow<'_, T>;
175}
176
177impl SmartClone<str> for String {
178 fn smart_clone(&self) -> std::borrow::Cow<'_, str> {
179 std::borrow::Cow::Borrowed(self)
180 }
181}
182
183impl<T: Clone> SmartClone<[T]> for Vec<T> {
184 fn smart_clone(&self) -> std::borrow::Cow<'_, [T]> {
185 std::borrow::Cow::Borrowed(self)
186 }
187}
188
189pub struct SmartStats {
192 pub allocation_count: AtomicU64,
194 pub deallocation_count: AtomicU64,
195
196 pub detailed_stats: Mutex<DetailedStats>,
198}
199
200#[derive(Default)]
201pub struct DetailedStats {
202 pub allocation_sizes: Vec<usize>,
203 pub allocation_times: Vec<Duration>,
204 pub peak_memory: usize,
205}
206
207impl SmartStats {
208 pub fn new() -> Self {
209 Self {
210 allocation_count: AtomicU64::new(0),
211 deallocation_count: AtomicU64::new(0),
212 detailed_stats: Mutex::new(DetailedStats::default()),
213 }
214 }
215
216 pub fn record_allocation(&self) {
218 self.allocation_count.fetch_add(1, Ordering::Relaxed);
219 }
220
221 pub fn record_detailed_allocation(&self, size: usize, time: Duration) {
223 self.allocation_count.fetch_add(1, Ordering::Relaxed);
224
225 if let Some(mut stats) = self.detailed_stats.try_lock() {
227 stats.allocation_sizes.push(size);
228 stats.allocation_times.push(time);
229 }
230 }
232
233 pub fn get_simple_stats(&self) -> (u64, u64) {
234 (
235 self.allocation_count.load(Ordering::Relaxed),
236 self.deallocation_count.load(Ordering::Relaxed),
237 )
238 }
239}
240
241impl Default for SmartStats {
242 fn default() -> Self {
243 Self::new()
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250 use std::sync::Arc;
251 use std::thread;
252
253 #[test]
254 fn test_smart_mutex_basic() {
255 let mutex = SmartMutex::new(42);
256 {
257 let guard = mutex.lock();
258 assert_eq!(*guard, 42);
259 }
260
261 {
262 let mut guard = mutex.lock();
263 *guard = 100;
264 }
265
266 {
267 let guard = mutex.lock();
268 assert_eq!(*guard, 100);
269 }
270 }
271
272 #[test]
273 fn test_smart_mutex_try_lock() {
274 let mutex = SmartMutex::new("test_value");
275
276 if let Some(guard) = mutex.try_lock() {
278 assert_eq!(*guard, "test_value");
279 } else {
280 panic!("try_lock should succeed when mutex is not held");
281 }
282
283 let mutex2 = Arc::new(SmartMutex::new(0));
285 let mutex2_clone = mutex2.clone();
286
287 let _guard = mutex2.lock();
288 assert!(mutex2_clone.try_lock().is_none());
290 }
291
292 #[test]
293 fn test_smart_mutex_parking_lot() {
294 let mutex = SmartMutex::ParkingLot(parking_lot::Mutex::new("parking_lot_test"));
296
297 {
298 let guard = mutex.lock();
299 assert_eq!(*guard, "parking_lot_test");
300 }
301
302 {
304 if let Some(guard) = mutex.try_lock() {
305 assert_eq!(*guard, "parking_lot_test");
306 } else {
307 panic!("ParkingLot try_lock should succeed");
308 };
309 }
310 }
311
312 #[test]
313 fn test_smart_mutex_guard_deref() {
314 let mutex = SmartMutex::new(vec![1, 2, 3]);
315 let guard = mutex.lock();
316
317 assert_eq!(guard.len(), 3);
319 assert_eq!(guard[0], 1);
320 }
321
322 #[test]
323 fn test_smart_mutex_guard_deref_mut() {
324 let mutex = SmartMutex::new(vec![1, 2, 3]);
325 let mut guard = mutex.lock();
326
327 guard.push(4);
329 assert_eq!(guard.len(), 4);
330 guard[0] = 10;
331 assert_eq!(guard[0], 10);
332 }
333
334 #[test]
335 fn test_contention_recording() {
336 let initial_count = CONTENTION_COUNTER.load(Ordering::Relaxed);
338 let initial_wait = TOTAL_WAIT_TIME_NS.load(Ordering::Relaxed);
339
340 record_contention("test_mutex", Duration::from_micros(50));
342
343 assert_eq!(
344 CONTENTION_COUNTER.load(Ordering::Relaxed),
345 initial_count + 1
346 );
347 assert!(TOTAL_WAIT_TIME_NS.load(Ordering::Relaxed) > initial_wait);
348
349 for _ in 0..10 {
351 record_contention("test_mutex", Duration::from_micros(100));
352 }
353
354 assert_eq!(
355 CONTENTION_COUNTER.load(Ordering::Relaxed),
356 initial_count + 11
357 );
358 }
359
360 #[test]
361 fn test_safe_unwrap_option() {
362 let some_value = Some(42);
364 assert_eq!(some_value.safe_unwrap(0), 42);
365
366 let none_value: Option<i32> = None;
368 assert_eq!(none_value.safe_unwrap(99), 99);
369
370 let some_string = Some("hello".to_string());
372 assert_eq!(some_string.safe_unwrap("default".to_string()), "hello");
373
374 let none_string: Option<String> = None;
375 assert_eq!(none_string.safe_unwrap("fallback".to_string()), "fallback");
376 }
377
378 #[test]
379 fn test_safe_unwrap_or_log_option() {
380 let some_value = Some(100);
382 assert_eq!(some_value.safe_unwrap_or_log("test_context", 0), 100);
383
384 let none_value: Option<i32> = None;
386 assert_eq!(none_value.safe_unwrap_or_log("none_context", 50), 50);
387
388 let some_vec = Some(vec![1, 2, 3]);
390 assert_eq!(
391 some_vec.safe_unwrap_or_log("vec_context", vec![]),
392 vec![1, 2, 3]
393 );
394 }
395
396 #[test]
397 fn test_safe_unwrap_result() {
398 let ok_result: Result<i32, String> = Ok(42);
400 assert_eq!(ok_result.safe_unwrap(0), 42);
401
402 #[cfg(not(debug_assertions))]
404 {
405 let err_result: Result<i32, String> = Err("error message".to_string());
406 assert_eq!(err_result.safe_unwrap(99), 99);
407 }
408
409 #[cfg(debug_assertions)]
411 {
412 let ok_result2: Result<String, &str> = Ok("success".to_string());
414 assert_eq!(ok_result2.safe_unwrap("fallback".to_string()), "success");
415 }
416 }
417
418 #[test]
419 fn test_safe_unwrap_or_log_result() {
420 let ok_result: Result<i32, String> = Ok(100);
422 assert_eq!(ok_result.safe_unwrap_or_log("ok_context", 0), 100);
423
424 let err_result: Result<i32, String> = Err("test error".to_string());
426 assert_eq!(err_result.safe_unwrap_or_log("err_context", 50), 50);
427
428 let err_result2: Result<Vec<u8>, std::io::Error> = Err(std::io::Error::new(
430 std::io::ErrorKind::NotFound,
431 "not found",
432 ));
433 assert_eq!(
434 err_result2.safe_unwrap_or_log("io_err", vec![1, 2]),
435 vec![1, 2]
436 );
437 }
438
439 #[test]
440 fn test_smart_clone_string() {
441 let string = String::from("hello world");
442 let cloned = string.smart_clone();
443
444 assert!(matches!(cloned, std::borrow::Cow::Borrowed(_)));
446 assert_eq!(&*cloned, "hello world");
447 }
448
449 #[test]
450 fn test_smart_clone_vec() {
451 let vec = vec![1, 2, 3, 4, 5];
452 let cloned = vec.smart_clone();
453
454 assert!(matches!(cloned, std::borrow::Cow::Borrowed(_)));
456 assert_eq!(&*cloned, &[1, 2, 3, 4, 5]);
457
458 let string_vec = vec!["a".to_string(), "b".to_string()];
460 let cloned2 = string_vec.smart_clone();
461 assert!(matches!(cloned2, std::borrow::Cow::Borrowed(_)));
462 assert_eq!(cloned2.len(), 2);
463 }
464
465 #[test]
466 fn test_smart_stats_basic() {
467 let stats = SmartStats::new();
468
469 let (allocs, deallocs) = stats.get_simple_stats();
471 assert_eq!(allocs, 0);
472 assert_eq!(deallocs, 0);
473
474 for _ in 0..100 {
476 stats.record_allocation();
477 }
478
479 let (allocs, deallocs) = stats.get_simple_stats();
480 assert_eq!(allocs, 100);
481 assert_eq!(deallocs, 0);
482
483 for _ in 0..50 {
485 stats.deallocation_count.fetch_add(1, Ordering::Relaxed);
486 }
487
488 let (allocs, deallocs) = stats.get_simple_stats();
489 assert_eq!(allocs, 100);
490 assert_eq!(deallocs, 50);
491 }
492
493 #[test]
494 fn test_smart_stats_detailed() {
495 let stats = SmartStats::new();
496
497 stats.record_detailed_allocation(1024, Duration::from_micros(10));
499 stats.record_detailed_allocation(2048, Duration::from_micros(20));
500 stats.record_detailed_allocation(512, Duration::from_micros(5));
501
502 let (allocs, _) = stats.get_simple_stats();
504 assert_eq!(allocs, 3);
505
506 let detailed = stats.detailed_stats.lock();
508 assert_eq!(detailed.allocation_sizes.len(), 3);
509 assert_eq!(detailed.allocation_sizes[0], 1024);
510 assert_eq!(detailed.allocation_sizes[1], 2048);
511 assert_eq!(detailed.allocation_sizes[2], 512);
512
513 assert_eq!(detailed.allocation_times.len(), 3);
514 assert_eq!(detailed.allocation_times[0], Duration::from_micros(10));
515 }
516
517 #[test]
518 fn test_smart_stats_peak_memory() {
519 let stats = SmartStats::new();
520
521 {
523 let mut detailed = stats.detailed_stats.lock();
524 detailed.peak_memory = 1000;
525 detailed.allocation_sizes.push(500);
526 }
527
528 let detailed = stats.detailed_stats.lock();
530 assert_eq!(detailed.peak_memory, 1000);
531 assert_eq!(detailed.allocation_sizes[0], 500);
532 }
533
534 #[test]
535 fn test_smart_stats_concurrent() {
536 let stats = Arc::new(SmartStats::new());
537 let mut handles = vec![];
538
539 for _ in 0..10 {
541 let stats_clone = stats.clone();
542 let handle = thread::spawn(move || {
543 for _ in 0..100 {
544 stats_clone.record_allocation();
545 }
546 });
547 handles.push(handle);
548 }
549
550 for handle in handles {
551 handle.join().unwrap();
552 }
553
554 let (allocs, _) = stats.get_simple_stats();
555 assert_eq!(allocs, 1000);
556 }
557
558 #[test]
559 fn test_smart_stats_default() {
560 let stats = SmartStats::default();
561 let (allocs, deallocs) = stats.get_simple_stats();
562 assert_eq!(allocs, 0);
563 assert_eq!(deallocs, 0);
564
565 let detailed = stats.detailed_stats.lock();
567 assert!(detailed.allocation_sizes.is_empty());
568 assert!(detailed.allocation_times.is_empty());
569 assert_eq!(detailed.peak_memory, 0);
570 }
571
572 #[test]
573 fn test_detailed_stats_default() {
574 let detailed = DetailedStats::default();
575 assert!(detailed.allocation_sizes.is_empty());
576 assert!(detailed.allocation_times.is_empty());
577 assert_eq!(detailed.peak_memory, 0);
578 }
579}