use core::ops::Deref;
use core::sync::atomic::AtomicPtr;
use mnemosyne_core::constants::NUM_SIZE_CLASSES;
use std::boxed::Box;
use std::sync::OnceLock;
use super::state::{MAX_CACHED_BLOCKS, NUM_CPU_SLOTS};
#[repr(align(64))]
pub struct CpuCacheSlot {
pub blocks: [[AtomicPtr<u8>; MAX_CACHED_BLOCKS]; NUM_SIZE_CLASSES],
}
impl Default for CpuCacheSlot {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl CpuCacheSlot {
pub const fn new() -> Self {
Self {
blocks: [const { [const { AtomicPtr::new(core::ptr::null_mut()) }; MAX_CACHED_BLOCKS] };
NUM_SIZE_CLASSES],
}
}
}
#[repr(align(64))]
pub struct PerCpuCache {
pub slots: [CpuCacheSlot; NUM_CPU_SLOTS],
}
impl Default for PerCpuCache {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl PerCpuCache {
pub const fn new() -> Self {
Self {
slots: [const { CpuCacheSlot::new() }; NUM_CPU_SLOTS],
}
}
}
pub struct PerCpuCacheHandle {
pub(super) storage: OnceLock<Box<PerCpuCache>>,
}
impl PerCpuCacheHandle {
pub const fn new() -> Self {
Self {
storage: OnceLock::new(),
}
}
#[inline]
pub(super) fn get(&self) -> &PerCpuCache {
self.storage
.get_or_init(|| Box::new(PerCpuCache::new()))
.as_ref()
}
}
impl Default for PerCpuCacheHandle {
fn default() -> Self {
Self::new()
}
}
impl Deref for PerCpuCacheHandle {
type Target = PerCpuCache;
#[inline]
fn deref(&self) -> &Self::Target {
self.get()
}
}