#[cfg(feature = "std")]
use std::sync::Mutex;
#[cfg(not(feature = "std"))]
use iceoryx2_pal_concurrency_sync::spin_lock::SpinLock as Mutex;
use iceoryx2_bb_elementary_traits::testing::abandonable::Abandonable;
use core::ptr::NonNull;
static CREATION_COUNTER: Mutex<usize> = Mutex::new(0);
static DROP_COUNTER: Mutex<usize> = Mutex::new(0);
static LEAK_COUNTER: Mutex<usize> = Mutex::new(0);
#[derive(Debug)]
pub struct AbandonTrackingState {}
impl AbandonTrackingState {
pub fn creation_count(&self) -> usize {
*CREATION_COUNTER.lock().unwrap_or_else(|e| e.into_inner())
}
pub fn drop_count(&self) -> usize {
*DROP_COUNTER.lock().unwrap_or_else(|e| e.into_inner())
}
pub fn abandon_count(&self) -> usize {
*LEAK_COUNTER.lock().unwrap_or_else(|e| e.into_inner())
}
}
#[repr(C)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct AbandonTacker {
pub value: usize,
}
impl Abandonable for AbandonTacker {
unsafe fn abandon_in_place(_this: NonNull<Self>) {
*LEAK_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) += 1;
}
}
impl Default for AbandonTacker {
fn default() -> Self {
*CREATION_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) += 1;
Self { value: 0 }
}
}
impl AbandonTacker {
pub fn new() -> Self {
Self::default()
}
pub fn new_with_value(value: usize) -> Self {
let mut new_self = Self::new();
new_self.value = value;
new_self
}
pub fn start_tracking() -> AbandonTrackingState {
*CREATION_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) = 0;
*LEAK_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) = 0;
*DROP_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) = 0;
AbandonTrackingState {}
}
}
impl Clone for AbandonTacker {
fn clone(&self) -> Self {
let mut new_self = Self::new();
new_self.value = self.value;
new_self
}
}
impl Drop for AbandonTacker {
fn drop(&mut self) {
*DROP_COUNTER.lock().unwrap_or_else(|e| e.into_inner()) += 1;
}
}