pub(crate) const MIN_CHUNK_BYTES: usize = 512;
pub(crate) const MAX_CHUNK_BYTES: usize = 65_536;
pub(crate) const CHUNK_ALIGN: usize = MAX_CHUNK_BYTES;
#[cfg_attr(test, mutants::skip)] #[inline]
pub(crate) const fn max_smart_ptr_align() -> usize {
CHUNK_ALIGN / 2
}
pub(crate) const NUM_CHUNK_CLASSES: u8 = 8;
pub(crate) const MAX_NORMAL_ALLOC: usize = 16 * 1024;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[repr(transparent)]
pub(crate) struct SizeClass(u8);
impl SizeClass {
pub(crate) const ZERO: Self = Self(0);
pub(crate) const MAX: Self = Self(NUM_CHUNK_CLASSES - 1);
#[inline]
#[must_use]
pub(crate) const fn new(c: u8) -> Self {
debug_assert!(c < NUM_CHUNK_CLASSES, "class out of range");
Self(c)
}
#[inline]
#[must_use]
pub(crate) const fn raw(self) -> u8 {
self.0
}
#[inline]
#[must_use]
pub(crate) const fn bytes(self) -> usize {
MIN_CHUNK_BYTES << self.0
}
#[inline]
#[must_use]
pub(crate) const fn min_for_bytes(bytes: usize) -> Self {
if bytes <= MIN_CHUNK_BYTES {
return Self::ZERO;
}
if bytes >= MAX_CHUNK_BYTES {
return Self::MAX;
}
let ratio = bytes.div_ceil(MIN_CHUNK_BYTES);
let mut c: u8 = 0;
let mut v: usize = 1;
while v < ratio {
v <<= 1;
c += 1;
}
Self(c)
}
#[inline]
#[must_use]
pub(crate) const fn saturating_inc(self) -> Self {
let next = self.0.saturating_add(1);
if next >= NUM_CHUNK_CLASSES { Self::MAX } else { Self(next) }
}
#[inline]
#[must_use]
pub(crate) const fn max(self, other: Self) -> Self {
if self.0 >= other.0 { self } else { other }
}
#[inline]
#[must_use]
pub(crate) const fn min(self, cap: Self) -> Self {
if self.0 <= cap.0 { self } else { cap }
}
}
#[cold]
#[inline(never)]
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg_attr(test, mutants::skip)] pub(crate) fn refcount_overflow_abort() -> ! {
#[cfg(test)]
{
panic!("multitude: refcount overflow (test)");
}
#[cfg(all(feature = "std", not(test)))]
{
std::process::abort();
}
#[cfg(all(not(feature = "std"), not(test)))]
{
struct ForceAbort;
impl Drop for ForceAbort {
fn drop(&mut self) {
panic!("multitude: chunk refcount overflow (abort)");
}
}
let _force = ForceAbort;
panic!("multitude: chunk refcount overflow");
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn max_smart_ptr_align_is_half_chunk_align() {
assert_eq!(max_smart_ptr_align(), CHUNK_ALIGN / 2);
}
#[test]
fn size_class_raw_round_trips_every_index() {
for i in 0..NUM_CHUNK_CLASSES {
assert_eq!(SizeClass::new(i).raw(), i);
}
}
}