use core::alloc::GlobalAlloc;
pub use core::alloc::Layout;
use core::sync::atomic::{fence, Ordering};
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum AllocAction {
Alloc,
AllocResult { ptr: *mut u8 },
AllocZeroed,
AllocZeroedResult { ptr: *mut u8 },
Dealloc { ptr: *mut u8 },
DeallocResult,
Realloc { ptr: *mut u8, new_size: usize },
ReallocResult { ptr: *mut u8, new_size: usize },
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum AllocRel {
Before,
After,
}
impl AllocAction {
#[inline]
pub fn relation(&self) -> AllocRel {
use AllocAction::*;
match self {
Alloc | AllocZeroed => AllocRel::Before,
Dealloc { ptr: _ } => AllocRel::Before,
Realloc {
ptr: _,
new_size: _,
} => AllocRel::Before,
_ => AllocRel::After,
}
}
}
pub struct InterAlloc<'a, T, F>
where
T: GlobalAlloc,
F: AllocMonitor,
{
pub inner: T,
pub monitor: &'a F,
}
impl<'a, T, F> InterAlloc<'a, T, F>
where
T: GlobalAlloc,
F: AllocMonitor,
{
#[inline]
pub fn new(base: T, monitor: &'a F) -> Self {
Self {
inner: base,
monitor: monitor,
}
}
#[inline]
fn monitor_(&self, layout: Layout, act: AllocAction) {
self.monitor.monitor(layout, act);
}
}
unsafe impl<'a, T, F> GlobalAlloc for InterAlloc<'a, T, F>
where
T: GlobalAlloc,
F: AllocMonitor,
{
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
self.monitor_(layout, AllocAction::Alloc);
fence(Ordering::SeqCst);
let ptr = self.inner.alloc(layout);
fence(Ordering::SeqCst);
self.monitor_(layout, AllocAction::AllocResult { ptr });
ptr
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
self.monitor_(layout, AllocAction::Dealloc { ptr });
fence(Ordering::SeqCst);
self.inner.dealloc(ptr, layout);
fence(Ordering::SeqCst);
self.monitor_(layout, AllocAction::DeallocResult);
}
#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
self.monitor_(layout, AllocAction::AllocZeroed);
fence(Ordering::SeqCst);
let ptr = self.inner.alloc_zeroed(layout);
fence(Ordering::SeqCst);
self.monitor_(layout, AllocAction::AllocZeroedResult { ptr });
ptr
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
self.monitor_(layout, AllocAction::Realloc { ptr, new_size });
fence(Ordering::SeqCst);
let ptr = self.inner.realloc(ptr, layout, new_size);
fence(Ordering::SeqCst);
self.monitor_(layout, AllocAction::ReallocResult { ptr, new_size });
ptr
}
}
pub trait AllocMonitor {
fn monitor(&self, layout: Layout, act: AllocAction);
}