use core::alloc::Layout;
use core::ptr::{self, NonNull};
use allocator_api2::alloc::{AllocError, Allocator};
use crate::Arena;
use crate::arena::alloc_value::acquire_shared_chunk_ref;
use crate::internal::chunk_ref::ChunkRef;
use crate::internal::constants::max_smart_ptr_align;
const MAX_SMART_PTR_ALIGN: usize = max_smart_ptr_align();
unsafe impl<A: Allocator + Clone> Allocator for &Arena<A> {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
if layout.align() >= MAX_SMART_PTR_ALIGN {
return Err(AllocError);
}
if layout.size() == 0 {
let dangling = unsafe { NonNull::new_unchecked(ptr::without_provenance_mut::<u8>(layout.align())) };
return Ok(NonNull::slice_from_raw_parts(dangling, 0));
}
let refill_hint = layout.size().saturating_add(layout.align());
loop {
if let Some((slot, chunk_ptr)) = self.current_shared().try_alloc_with_chunk(layout.size(), layout.align()) {
let chunk_ref = self.acquire_current_shared_chunk_ref(chunk_ptr);
let ptr = slot.as_non_null();
let _ = chunk_ref.forget();
return Ok(NonNull::slice_from_raw_parts(ptr, layout.size()));
}
if self.is_oversized_shared(refill_hint) {
return self.alloc_oversized_shared_with(refill_hint, |mutator, chunk_ptr| {
let (slot, _chunk) = mutator
.try_alloc_with_chunk(layout.size(), layout.align())
.expect("dedicated oversized chunk sized to fit allocation + alignment slack");
let chunk_ref = acquire_shared_chunk_ref::<A>(chunk_ptr);
let ptr = slot.as_non_null();
let _ = chunk_ref.forget();
NonNull::slice_from_raw_parts(ptr, layout.size())
});
}
self.refill_shared(refill_hint)?;
}
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
if layout.size() == 0 {
return;
}
let _ref: ChunkRef<A> = unsafe { ChunkRef::from_value_ptr(ptr) };
}
unsafe fn grow(&self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let new = self.allocate(new_layout)?;
let copy_bytes = old_layout.size().min(new_layout.size());
if copy_bytes != 0 {
unsafe {
ptr::copy_nonoverlapping(ptr.as_ptr(), new.cast::<u8>().as_ptr(), copy_bytes);
}
}
unsafe { self.deallocate(ptr, old_layout) };
Ok(new)
}
}