#![allow(unsafe_op_in_unsafe_fn, reason = "see module doc: inner unsafe blocks in unsafe fn add noise here")]
#![allow(clippy::unnecessary_safety_comment, reason = "safety rationale documented at function level")]
use core::ptr::NonNull;
use allocator_api2::alloc::Allocator;
use super::chunk::Chunk;
use super::local_chunk::LocalChunk;
use super::shared_chunk::SharedChunk;
pub(crate) trait ChunkOps: Chunk {
type Allocator: Allocator + Clone;
unsafe fn payload_ptr(chunk: NonNull<Self>) -> NonNull<u8>;
unsafe fn teardown_and_release(chunk: NonNull<Self>);
}
#[allow(
clippy::use_self,
reason = "must call inherent methods, not the trait Self methods, to avoid infinite recursion"
)]
impl<A: Allocator + Clone> ChunkOps for LocalChunk<A> {
type Allocator = A;
#[inline]
unsafe fn payload_ptr(chunk: NonNull<Self>) -> NonNull<u8> {
LocalChunk::payload_ptr(chunk)
}
#[cold]
#[inline(never)]
unsafe fn teardown_and_release(chunk: NonNull<Self>) {
let chunk_ref = &*chunk.as_ptr();
let drop_count = chunk_ref.drop_entry_count();
if drop_count != 0 {
let payload = LocalChunk::payload_ptr(chunk).as_ptr();
let capacity = chunk_ref.capacity();
super::drop_entry::replay_drops(payload, capacity, drop_count);
chunk_ref.set_drop_entry_count(0);
}
let provider = chunk_ref.provider();
debug_assert!(!provider.is_null(), "local-chunk provider back-pointer is null in teardown");
(*provider).release_local(chunk);
}
}
#[allow(
clippy::use_self,
reason = "must call inherent methods, not the trait Self methods, to avoid infinite recursion"
)]
impl<A: Allocator + Clone> ChunkOps for SharedChunk<A> {
type Allocator = A;
#[inline]
unsafe fn payload_ptr(chunk: NonNull<Self>) -> NonNull<u8> {
SharedChunk::payload_ptr(chunk)
}
#[cold]
#[inline(never)]
unsafe fn teardown_and_release(chunk: NonNull<Self>) {
let chunk_ref = &*chunk.as_ptr();
let drop_count = chunk_ref.drop_entry_count();
if drop_count != 0 {
let payload = SharedChunk::payload_ptr(chunk).as_ptr();
let capacity = chunk_ref.capacity();
super::drop_entry::replay_drops(payload, capacity, drop_count);
chunk_ref.set_drop_entry_count(0);
}
if let Some(provider) = chunk_ref.provider().upgrade() {
provider.release_shared(chunk);
} else {
SharedChunk::destroy(chunk);
}
}
}