use core::ptr::NonNull;
use mnemosyne_core::policy::AllocPolicy;
use mnemosyne_core::types::{Block, Page};
#[inline(always)]
pub(crate) unsafe fn pop_page_free_block<P: AllocPolicy>(page: &mut Page) -> NonNull<Block> {
unsafe { page.pop_block::<P>() }
}
#[inline(always)]
pub(crate) unsafe fn try_allocate_page_local<P: AllocPolicy>(
page: &mut Page,
) -> Option<NonNull<Block>> {
if page.free.is_none() && page.initialized_blocks >= page.max_blocks() {
return None;
}
let block = unsafe { page.pop_block::<P>() };
unsafe { page.increment_alloc_count() };
Some(block)
}
#[inline(always)]
pub(crate) unsafe fn try_reclaim_and_allocate<P: AllocPolicy>(
page: &mut Page,
reclaim_sink: &mut usize,
) -> Option<NonNull<Block>> {
if page.thread_free.is_empty() {
return None;
}
let segment = page.parent_segment();
let page_index = page.index_in_segment();
let reclaimed = unsafe {
page.reclaim_thread_free_dynamic_for_segment(
P::ENABLE_FREE_LIST_ENCRYPTION,
segment,
page_index,
)
};
if reclaimed == 0 {
return None;
}
*reclaim_sink += reclaimed;
let block = unsafe { try_allocate_page_local::<P>(page) }
.expect("invariant: reclaimed remote frees populate the page-local free list");
Some(block)
}