rust_cc/
counter_marker.rsuse core::cell::Cell;
use crate::utils;
const NON_MARKED: u16 = 0u16;
const IN_POSSIBLE_CYCLES: u16 = 1u16 << (u16::BITS - 2);
const IN_LIST: u16 = 2u16 << (u16::BITS - 2);
const IN_QUEUE: u16 = 3u16 << (u16::BITS - 2);
const COUNTER_MASK: u16 = 0b11111111111111u16; const FIRST_BIT_MASK: u16 = 1u16 << (u16::BITS - 1);
const FINALIZED_MASK: u16 = 1u16 << (u16::BITS - 2);
const BITS_MASK: u16 = !COUNTER_MASK;
const INITIAL_VALUE: u16 = 1u16;
const INITIAL_VALUE_TRACING_COUNTER: u16 = INITIAL_VALUE | NON_MARKED;
const INITIAL_VALUE_FINALIZED: u16 = INITIAL_VALUE | FINALIZED_MASK;
pub(crate) const MAX: u16 = COUNTER_MASK - 1;
#[derive(Clone, Debug)]
pub(crate) struct CounterMarker {
tracing_counter: Cell<u16>,
counter: Cell<u16>,
}
pub(crate) struct OverflowError;
impl CounterMarker {
#[inline]
#[must_use]
pub(crate) fn new_with_counter_to_one(already_finalized: bool) -> CounterMarker {
CounterMarker {
tracing_counter: Cell::new(INITIAL_VALUE_TRACING_COUNTER),
counter: Cell::new(if !already_finalized {
INITIAL_VALUE
} else {
INITIAL_VALUE_FINALIZED
}),
}
}
#[inline]
pub(crate) fn increment_counter(&self) -> Result<(), OverflowError> {
debug_assert!(self.counter() != COUNTER_MASK); if self.counter() == MAX {
utils::cold(); Err(OverflowError)
} else {
self.counter.set(self.counter.get() + 1);
Ok(())
}
}
#[inline]
pub(crate) fn decrement_counter(&self) -> Result<(), OverflowError> {
debug_assert!(self.counter() != COUNTER_MASK); if self.counter() == 0 {
utils::cold(); Err(OverflowError)
} else {
self.counter.set(self.counter.get() - 1);
Ok(())
}
}
#[inline]
pub(crate) fn increment_tracing_counter(&self) -> Result<(), OverflowError> {
debug_assert!(self.tracing_counter() != COUNTER_MASK); if self.tracing_counter() == MAX {
utils::cold(); Err(OverflowError)
} else {
self.tracing_counter.set(self.tracing_counter.get() + 1);
Ok(())
}
}
#[inline]
pub(crate) fn _decrement_tracing_counter(&self) -> Result<(), OverflowError> {
debug_assert!(self.tracing_counter() != COUNTER_MASK); if self.tracing_counter() == 0 {
utils::cold(); Err(OverflowError)
} else {
self.tracing_counter.set(self.tracing_counter.get() - 1);
Ok(())
}
}
#[inline]
pub(crate) fn counter(&self) -> u16 {
let rc = self.counter.get() & COUNTER_MASK;
debug_assert!(rc != COUNTER_MASK); rc
}
#[inline]
pub(crate) fn tracing_counter(&self) -> u16 {
let tc = self.tracing_counter.get() & COUNTER_MASK;
debug_assert!(tc != COUNTER_MASK); tc
}
#[inline]
pub(crate) fn reset_tracing_counter(&self) {
debug_assert!(self.tracing_counter() != COUNTER_MASK); self.tracing_counter.set(self.tracing_counter.get() & !COUNTER_MASK);
}
#[cfg(feature = "finalization")]
#[inline]
pub(crate) fn needs_finalization(&self) -> bool {
(self.counter.get() & FINALIZED_MASK) == 0u16
}
#[cfg(feature = "finalization")]
#[inline]
pub(crate) fn set_finalized(&self, finalized: bool) {
Self::set_bits(&self.counter, finalized, FINALIZED_MASK);
}
#[cfg(feature = "weak-ptrs")]
#[inline]
pub(crate) fn has_allocated_for_metadata(&self) -> bool {
(self.counter.get() & FIRST_BIT_MASK) == FIRST_BIT_MASK
}
#[cfg(feature = "weak-ptrs")]
#[inline]
pub(crate) fn set_allocated_for_metadata(&self, allocated_for_metadata: bool) {
Self::set_bits(&self.counter, allocated_for_metadata, FIRST_BIT_MASK);
}
#[cfg(feature = "weak-ptrs")]
#[inline]
pub(crate) fn is_dropped(&self) -> bool {
(self.tracing_counter.get() & COUNTER_MASK) == COUNTER_MASK
}
#[cfg(feature = "weak-ptrs")]
#[inline]
pub(crate) fn set_dropped(&self, dropped: bool) {
Self::set_bits(&self.tracing_counter, dropped, COUNTER_MASK);
}
#[inline]
pub(crate) fn is_not_marked(&self) -> bool {
(self.tracing_counter.get() & FIRST_BIT_MASK) == 0u16
}
#[inline]
pub(crate) fn is_in_possible_cycles(&self) -> bool {
(self.tracing_counter.get() & BITS_MASK) == IN_POSSIBLE_CYCLES
}
#[inline]
pub(crate) fn is_in_list(&self) -> bool {
(self.tracing_counter.get() & BITS_MASK) == IN_LIST
}
#[inline]
pub(crate) fn _is_in_queue(&self) -> bool {
(self.tracing_counter.get() & BITS_MASK) == IN_QUEUE
}
#[inline]
pub(crate) fn is_in_list_or_queue(&self) -> bool {
(self.tracing_counter.get() & FIRST_BIT_MASK) == FIRST_BIT_MASK
}
#[inline]
pub(crate) fn mark(&self, new_mark: Mark) {
self.tracing_counter.set((self.tracing_counter.get() & !BITS_MASK) | (new_mark as u16));
}
#[cfg(any(feature = "weak-ptrs", feature = "finalization"))]
#[inline(always)]
fn set_bits(cell: &Cell<u16>, value: bool, mask: u16) {
if value {
cell.set(cell.get() | mask);
} else {
cell.set(cell.get() & !mask);
}
}
}
#[derive(Copy, Clone, Debug)]
#[repr(u16)]
pub(crate) enum Mark {
NonMarked = NON_MARKED,
PossibleCycles = IN_POSSIBLE_CYCLES,
InList = IN_LIST,
InQueue = IN_QUEUE,
}