use std::{
alloc::{GlobalAlloc, Layout, System},
ptr::NonNull,
};
use crate::generated::fixed_size_constants::{BLOCK_ALIGN, BLOCK_SIZE};
use super::super::{Arena, ChunkFooter};
const TWO_GIB: usize = 1 << 31;
const FOUR_GIB: usize = 1 << 32;
const ALLOC_SIZE: usize = BLOCK_SIZE + TWO_GIB;
const ALLOC_ALIGN: usize = TWO_GIB;
const _: () = {
assert!(BLOCK_SIZE <= TWO_GIB);
assert!(BLOCK_ALIGN == FOUR_GIB);
};
const ALLOC_LAYOUT: Layout = match Layout::from_size_align(ALLOC_SIZE, ALLOC_ALIGN) {
Ok(layout) => layout,
Err(_) => unreachable!(),
};
const _: () = assert!(ALLOC_LAYOUT.size() > 0);
impl<const MIN_ALIGN: usize> Arena<MIN_ALIGN> {
pub fn new_fixed_size() -> Option<Self> {
let alloc_ptr = unsafe { System.alloc(ALLOC_LAYOUT) };
let alloc_ptr = NonNull::new(alloc_ptr)?;
let offset = alloc_ptr.addr().get() % FOUR_GIB;
let chunk_ptr = unsafe { alloc_ptr.add(offset) };
debug_assert!(chunk_ptr.addr().get().is_multiple_of(BLOCK_ALIGN));
let arena = unsafe { Self::from_raw_parts(chunk_ptr, BLOCK_SIZE, alloc_ptr, ALLOC_LAYOUT) };
Some(arena)
}
#[expect(unused_variables)]
#[cfg_attr(not(debug_assertions), expect(clippy::unused_self))]
#[inline(always)] pub(in super::super) unsafe fn grow_fixed_size_chunk(
&self,
layout: Layout,
) -> Option<NonNull<u8>> {
#[cfg(debug_assertions)]
{
let footer_ptr = self.current_chunk_footer_ptr.get().expect("Arena has no chunks");
let footer = unsafe { footer_ptr.as_ref() };
assert!(
footer.is_fixed_size,
"Only fixed-size allocators should be passed to `Arena::grow_fixed_size_chunk`"
);
}
None
}
}
pub unsafe fn dealloc_fixed_size_arena_chunk(footer_ptr: NonNull<ChunkFooter>) {
let (backing_alloc_ptr, layout, is_fixed_size) = {
let footer = unsafe { footer_ptr.as_ref() };
(footer.backing_alloc_ptr, footer.layout, footer.is_fixed_size)
};
debug_assert!(
is_fixed_size,
"Only fixed-size allocators should be passed to `dealloc_fixed_size_arena_chunk` to deallocate"
);
unsafe { System.dealloc(backing_alloc_ptr.as_ptr(), layout) };
}