use core::alloc::{GlobalAlloc, Layout};
use core::fmt;
use spin::Mutex;
use crate::{AllocatorStats, Statsable};
pub struct ThreadSafeAllocator<A: GlobalAlloc + Statsable + 'static> {
pub inner: Mutex<&'static A>,
}
unsafe impl<A: GlobalAlloc + Statsable> Sync for ThreadSafeAllocator<A> {}
impl<A: fmt::Display + GlobalAlloc + Statsable> fmt::Display for ThreadSafeAllocator<A> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ThreadSafeAllocator({})", self.inner.lock())
}
}
impl<A: GlobalAlloc + Statsable> ThreadSafeAllocator<A> {
pub const fn new(inner: &'static A) -> ThreadSafeAllocator<A> {
ThreadSafeAllocator { inner: Mutex::new(inner) }
}
}
unsafe impl<A: GlobalAlloc + Statsable> GlobalAlloc for ThreadSafeAllocator<A> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
unsafe { self.inner.lock().alloc(layout) }
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
unsafe { self.inner.lock().dealloc(ptr, layout) }
}
}
impl<A: GlobalAlloc + Statsable> Statsable for ThreadSafeAllocator<A> {
fn get_stats(&self) -> AllocatorStats {
self.inner.lock().get_stats()
}
fn reset_trip(&self) {
self.inner.lock().reset_trip()
}
}