use core::alloc::{GlobalAlloc, Layout};
use core::fmt;
use super::{AllocatorStats, Statsable};
use super::metrics::Metrics;
pub struct WrappedAllocator<A: GlobalAlloc + 'static> {
pub inner: &'static A,
metrics: Metrics,
}
unsafe impl<A: GlobalAlloc> Sync for WrappedAllocator<A> {}
impl<A: GlobalAlloc> fmt::Display for WrappedAllocator<A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SYSTEM")
}
}
impl<A: GlobalAlloc> WrappedAllocator<A> {
pub const fn new(inner: &'static A) -> WrappedAllocator<A> {
WrappedAllocator { inner, metrics: Metrics::new() }
}
}
unsafe impl<A: GlobalAlloc> GlobalAlloc for WrappedAllocator<A> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
self.metrics.add(layout);
unsafe { self.inner.alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
self.metrics.subtract(layout);
unsafe { self.inner.dealloc(ptr, layout) }
}
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
self.metrics.add(layout);
unsafe { self.inner.alloc_zeroed(layout) }
}
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
self.metrics.subtract(layout);
self.metrics.add(Layout::from_size_align(new_size, layout.align()).unwrap());
unsafe { self.inner.realloc(ptr, layout, new_size) }
}
}
impl<A: GlobalAlloc> Statsable for WrappedAllocator<A> {
fn get_stats(&self) -> AllocatorStats {
let mut stats = AllocatorStats::default();
self.metrics.get_stats(&mut stats);
stats
}
fn reset_trip(&self) {
self.metrics.reset_trip();
}
}