use super::HeadCodec;
use super::PackedTaggedPtr;
use crate::loom_shim::{AtomicPtr, Ordering};
use crate::types::Block;
pub(super) struct PackedHead;
impl HeadCodec for PackedHead {
const COUNT_REQUIRES_WALK: bool = false;
#[inline(always)]
fn load(head: &AtomicPtr<Block>, order: Ordering) -> *mut Block {
head.load(order)
}
#[inline(always)]
fn cas(
head: &AtomicPtr<Block>,
current: *mut Block,
next: *mut Block,
success: Ordering,
failure: Ordering,
) -> Result<*mut Block, *mut Block> {
head.compare_exchange_weak(current, next, success, failure)
}
#[inline(always)]
fn swap_null(head: &AtomicPtr<Block>, order: Ordering) -> *mut Block {
head.swap(core::ptr::null_mut(), order)
}
#[inline(always)]
fn addr(raw: *mut Block) -> *mut Block {
PackedTaggedPtr::<Block>::ptr(raw)
}
#[inline(always)]
fn assert_packable(addr: *mut Block) {
if let Err(reason) = PackedTaggedPtr::<Block>::checked_pack(addr) {
crate::abort::abort_on_corruption(reason);
}
}
#[inline(always)]
fn pack(addr: *mut Block, current: *mut Block) -> *mut Block {
PackedTaggedPtr::<Block>::tagged_successor(addr, current)
}
#[inline(always)]
fn validate(raw: *mut Block) {
if Self::addr(raw).is_null() && !raw.is_null() {
crate::abort::abort_on_corruption(
"AtomicFreeList head pointer is null while the packed count is non-zero",
);
}
}
#[inline(always)]
fn count_of(raw: *mut Block, walked: Option<usize>) -> usize {
let count = PackedTaggedPtr::<Block>::tag(raw);
if walked.is_some_and(|walked| walked != count) {
crate::abort::abort_on_corruption(
"AtomicFreeList packed count does not match the detached chain length",
);
}
count
}
}