refs 0.51.0

My vision of reference counting and resources management designed for GUI applications.
Documentation
use std::{
    collections::{HashMap, hash_map::Entry},
    sync::{
        OnceLock,
        atomic::{AtomicU64, Ordering},
    },
};

use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};

use crate::{Stamp, own::Addr};

static COUNTER: OnceLock<RefCounter> = OnceLock::new();

type Map = HashMap<Addr, Stamp>;

#[derive(Default)]
pub(crate) struct RefCounter {
    deallocators: RwLock<Map>,
}

impl RefCounter {
    fn counter() -> RwLockReadGuard<'static, Map> {
        COUNTER.get_or_init(RefCounter::default).deallocators.read()
    }

    fn counter_mut() -> RwLockWriteGuard<'static, Map> {
        COUNTER.get_or_init(RefCounter::default).deallocators.write()
    }

    pub(crate) fn stamp_for_address(addr: Addr) -> Option<Stamp> {
        Self::counter().get(&addr).copied()
    }

    pub(crate) fn add(
        addr: Addr,
        #[cfg(feature = "pointers_info")] location: &'static std::panic::Location,
    ) -> Stamp {
        let stamp = stamp();
        match Self::counter_mut().entry(addr) {
            Entry::Vacant(slot) => {
                slot.insert(stamp);
            }
            Entry::Occupied(slot) => {
                unreachable!(
                    "Adding deallocator of already existing address: {addr:#x} (existing stamp: {})",
                    slot.get()
                );
            }
        }

        #[cfg(feature = "pointers_info")]
        crate::pointers_info::PointerInfo::record_alloc(addr, stamp, location);

        stamp
    }

    pub(crate) fn remove(addr: Addr, #[cfg(feature = "pointers_info")] backtrace: std::backtrace::Backtrace) {
        Self::counter_mut().remove(&addr).expect("Removing non existing address");
        #[cfg(feature = "pointers_info")]
        crate::pointers_info::PointerInfo::record_dealloc(addr, stamp(), backtrace);
    }
}

fn stamp() -> Stamp {
    static NEXT: AtomicU64 = AtomicU64::new(1);
    NEXT.fetch_add(1, Ordering::Relaxed)
}