#![expect(
clippy::undocumented_unsafe_blocks,
reason = "the unsafe block is governed by the precondition documented on the surrounding function — the caller has a fresh allocation from a shared chunk under refcount discipline"
)]
use alloc::alloc::{alloc, dealloc, handle_alloc_error};
use core::alloc::Layout;
use core::mem::MaybeUninit;
use core::num::NonZero;
use core::ptr::{NonNull, drop_in_place, write};
use core::sync::atomic::{AtomicUsize, Ordering, fence};
use allocator_api2::alloc::Allocator;
use bytesbuf::BytesBuf;
use bytesbuf::mem::{Block, BlockRef, BlockRefDynamic, BlockRefVTable, Memory};
use crate::Arena;
use crate::internal::in_chunk::InSharedChunk;
use crate::internal::shared_chunk::SharedChunk;
impl<A: Allocator + Clone + Send + Sync + 'static> Memory for Arena<A> {
fn reserve(&self, min_bytes: usize) -> BytesBuf {
if min_bytes == 0 {
return BytesBuf::new();
}
let block_len = u32::try_from(min_bytes)
.expect("min_bytes exceeds u32::MAX bytes (just under 4 GiB), the per-reservation cap imposed by bytesbuf's BlockSize");
let block_len_nz = NonZero::new(block_len).expect("min_bytes is non-zero (handled above)");
let layout = Layout::from_size_align(min_bytes, 1).expect("byte layout with align 1 is always valid");
let data = self.allocate_shared_layout(layout).expect("arena allocation failed");
let state_layout = Layout::new::<ArenaBlockState>();
let raw_state = unsafe { alloc(state_layout) };
let state_nn = NonNull::new(raw_state).unwrap_or_else(|| abort_oom(state_layout));
let state_ptr: NonNull<ArenaBlockState> = state_nn.cast();
unsafe {
write(
state_ptr.as_ptr(),
ArenaBlockState {
data_ptr: data,
ref_count: AtomicUsize::new(1),
release_fn: release_chunk_ref_shared::<A>,
},
);
};
let block_ref = unsafe { BlockRef::new(state_ptr, &ARENA_BLOCK_VTABLE) };
let block = unsafe { Block::new(data.cast::<MaybeUninit<u8>>(), block_len_nz, block_ref) };
BytesBuf::from_blocks([block])
}
}
#[cold]
#[inline(never)]
#[cfg_attr(coverage_nightly, coverage(off))]
fn abort_oom(layout: Layout) -> ! {
handle_alloc_error(layout);
}
type ReleaseFn = unsafe fn(NonNull<u8>);
#[repr(C)]
struct ArenaBlockState {
data_ptr: NonNull<u8>,
ref_count: AtomicUsize,
release_fn: ReleaseFn,
}
unsafe impl Send for ArenaBlockState {}
unsafe impl Sync for ArenaBlockState {}
static ARENA_BLOCK_VTABLE: BlockRefVTable<ArenaBlockState> = BlockRefVTable::from_trait();
unsafe impl BlockRefDynamic for ArenaBlockState {
type State = Self;
fn clone(state_ptr: NonNull<Self::State>) -> NonNull<Self::State> {
let prev = unsafe { (*state_ptr.as_ptr()).ref_count.fetch_add(1, Ordering::Relaxed) };
check_arena_block_state_refcount(prev);
debug_assert!(prev > 0, "BlockRef::clone on a dead state");
state_ptr
}
fn drop(state_ptr: NonNull<Self::State>) {
let prev = unsafe { (*state_ptr.as_ptr()).ref_count.fetch_sub(1, Ordering::Release) };
debug_assert!(prev > 0, "BlockRef::drop on a dead state");
if prev == 1 {
fence(Ordering::Acquire);
let (data_ptr, release_fn) = unsafe {
let s = &*state_ptr.as_ptr();
(s.data_ptr, s.release_fn)
};
unsafe { release_fn(data_ptr) };
unsafe { drop_in_place(state_ptr.as_ptr()) };
let layout = Layout::new::<Self>();
unsafe { dealloc(state_ptr.as_ptr().cast::<u8>(), layout) };
}
}
}
#[inline(always)]
#[allow(
clippy::inline_always,
reason = "must inline at every clone site to avoid a per-call function-call overhead on the BlockRef::clone hot path"
)]
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg_attr(test, mutants::skip)] fn check_arena_block_state_refcount(prev: usize) {
use crate::internal::constants::{LARGE, refcount_overflow_abort};
if prev >= LARGE.saturating_add(LARGE) {
refcount_overflow_abort();
}
}
unsafe fn release_chunk_ref_shared<A: Allocator + Clone>(data_ptr: NonNull<u8>) {
let chunk = unsafe { InSharedChunk::<_, A>::new(data_ptr) }.chunk_ptr();
unsafe { SharedChunk::dec_ref(chunk) };
}