use core::ptr::NonNull;
use crate::class::{self, NCLASSES};
use crate::segment::Segment;
use super::Heap;
#[derive(Clone, Copy)]
pub(crate) struct Claim {
pub(crate) seg: NonNull<Segment>,
pub(crate) span_ix: u8,
pub(crate) word: u8,
pub(crate) claimed: u64,
pub(crate) taken: u64,
pub(crate) base: *mut u8,
}
impl Heap {
pub(super) fn pop_claimed(&mut self, c: usize) -> Option<NonNull<u8>> {
let cl = self.claims[c].as_mut()?;
let avail = cl.claimed & !cl.taken;
if avail == 0 {
return None;
}
let b = avail.trailing_zeros();
cl.taken |= 1u64 << b;
let i = u32::from(cl.word) * 64 + b;
NonNull::new(cl.base.wrapping_add(i as usize * class::size_of(c)))
}
pub(super) fn refill_claim(&mut self, c: usize) -> Option<()> {
self.retire_claim(c);
let (seg, span_ix) = self.partial[c]?;
let meta = unsafe { &mut (*seg.as_ptr()).spans[span_ix as usize] };
let Some((word, claimed)) = meta.claim_word() else {
self.partial[c] = None;
return None;
};
if meta.discarded != 0 {
let slot_size = class::size_of(c);
let lo = u32::from(word) * 64 + claimed.trailing_zeros();
let hi = u32::from(word) * 64 + (63 - claimed.leading_zeros());
let (pa, _) = crate::pagemap::pages_of_slot(lo, slot_size);
let (_, pb) = crate::pagemap::pages_of_slot(hi, slot_size);
for p in pa..=pb {
meta.discarded &= !(1u16 << p);
}
}
let base = unsafe { seg.as_ref() }.span_base(span_ix as usize);
self.claims[c] = Some(Claim { seg, span_ix, word, claimed, taken: 0, base });
Some(())
}
pub(super) fn retire_claim(&mut self, c: usize) {
let Some(cl) = self.claims[c].take() else { return };
let unused = cl.claimed & !cl.taken;
if unused == 0 {
return;
}
let meta = unsafe { &mut (*cl.seg.as_ptr()).spans[cl.span_ix as usize] };
meta.retire_word(cl.word, unused);
}
pub fn flush_claims(&mut self) {
for c in 0..NCLASSES {
self.retire_claim(c);
}
}
pub(crate) fn claims_unused_bytes(&self) -> u64 {
let mut sum = 0u64;
for (c, cl) in self.claims.iter().enumerate() {
if let Some(cl) = cl {
sum += u64::from((cl.claimed & !cl.taken).count_ones()) * class::size_of(c) as u64;
}
}
sum
}
}