use std::alloc::{Layout, System, GlobalAlloc};
pub trait VedaAllocator: Send + Sync + std::fmt::Debug {
fn allocate(&self, layout: Layout) -> *mut u8;
fn deallocate(&self, ptr: *mut u8, layout: Layout);
fn allocate_zeroed(&self, layout: Layout) -> *mut u8 {
let ptr = self.allocate(layout);
if !ptr.is_null() {
unsafe {
std::ptr::write_bytes(ptr, 0, layout.size());
}
}
ptr
}
fn reallocate(&self, ptr: *mut u8, old_layout: Layout, new_layout: Layout) -> *mut u8 {
let new_ptr = self.allocate(new_layout);
if !new_ptr.is_null() && !ptr.is_null() {
unsafe {
let copy_size = old_layout.size().min(new_layout.size());
std::ptr::copy_nonoverlapping(ptr, new_ptr, copy_size);
}
self.deallocate(ptr, old_layout);
}
new_ptr
}
}
#[derive(Debug)]
pub struct SystemAllocator;
impl VedaAllocator for SystemAllocator {
fn allocate(&self, layout: Layout) -> *mut u8 {
unsafe { System.alloc(layout) }
}
fn deallocate(&self, ptr: *mut u8, layout: Layout) {
unsafe { System.dealloc(ptr, layout) }
}
}
impl Default for SystemAllocator {
fn default() -> Self {
Self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_system_allocator() {
let allocator = SystemAllocator;
let layout = Layout::from_size_align(1024, 8).unwrap();
let ptr = allocator.allocate(layout);
assert!(!ptr.is_null());
allocator.deallocate(ptr, layout);
}
#[test]
fn test_allocate_zeroed() {
let allocator = SystemAllocator;
let layout = Layout::from_size_align(16, 8).unwrap();
let ptr = allocator.allocate_zeroed(layout);
assert!(!ptr.is_null());
unsafe {
for i in 0..16 {
assert_eq!(*ptr.add(i), 0);
}
}
allocator.deallocate(ptr, layout);
}
}