diff --git a/src/cc.rs b/src/cc.rs index 4f135f8..755265b 100644 --- a/src/cc.rs +++ b/src/cc.rs @@ -114,7 +114,7 @@ impl Cc { /// Returns the number of [`Cc`]s to the pointed allocation. #[inline] pub fn strong_count(&self) -> u32 { - self.counter_marker().counter() + self.counter_marker().counter() as u32 } /// Returns `true` if the strong reference count is `1`, `false` otherwise. diff --git a/src/counter_marker.rs b/src/counter_marker.rs index b0a2a3b..6391f38 100644 --- a/src/counter_marker.rs +++ b/src/counter_marker.rs @@ -2,29 +2,28 @@ use core::cell::Cell; use crate::utils; -const NON_MARKED: u32 = 0u32; -const IN_POSSIBLE_CYCLES: u32 = 1u32 << (u32::BITS - 2); -const IN_LIST: u32 = 2u32 << (u32::BITS - 2); -const IN_QUEUE: u32 = 3u32 << (u32::BITS - 2); +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: u32 = 0b11111111111111u32; // First 14 bits set to 1 -const TRACING_COUNTER_MASK: u32 = COUNTER_MASK << 14; // 14 bits set to 1 followed by 14 bits set to 0 -const FINALIZED_MASK: u32 = 1u32 << (u32::BITS - 4); -const METADATA_MASK: u32 = 1u32 << (u32::BITS - 3); -const BITS_MASK: u32 = !(COUNTER_MASK | TRACING_COUNTER_MASK | FINALIZED_MASK | METADATA_MASK); -const FIRST_BIT_MASK: u32 = 1u32 << (u32::BITS - 1); +const COUNTER_MASK: u16 = 0b11111111111111u16; // First 14 bits set to 1 +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: u32 = COUNTER_MASK + 2; // +2 means that tracing counter and counter are both set to 1 -const INITIAL_VALUE_FINALIZED: u32 = INITIAL_VALUE | FINALIZED_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) to make it available in tests -pub(crate) const MAX: u32 = COUNTER_MASK - 1; +pub(crate) const MAX: u16 = COUNTER_MASK - 1; /// Internal representation: /// ```text -/// +-----------+----------+----------+------------+------------+ -/// | A: 2 bits | B: 1 bit | C: 1 bit | D: 14 bits | E: 14 bits | Total: 32 bits -/// +-----------+----------+----------+------------+------------+ +/// +-----------+------------+ +----------+----------+------------+ +/// | A: 2 bits | B: 14 bits | | C: 1 bit | D: 1 bit | E: 14 bits | Total: 32 bits (16 + 16) +/// +-----------+------------+ +----------+----------+------------+ /// ``` /// /// * `A` has 4 possible states: @@ -32,16 +31,15 @@ pub(crate) const MAX: u32 = COUNTER_MASK - 1; /// * `IN_POSSIBLE_CYCLES`: in `possible_cycles` list (implies `NON_MARKED`) /// * `IN_LIST`: in `root_list` or `non_root_list` /// * `IN_QUEUE`: in queue to be traced -/// * `B` is `1` when metadata has been allocated, `0` otherwise -/// * `C` is `1` when the element inside `CcBox` has already been finalized, `0` otherwise -/// * `D` is the tracing counter. The max value (the one with every bit set to 1) is reserved +/// * `B` is the tracing counter. The max value (the one with every bit set to 1) is reserved /// and indicates that the allocated value has already been dropped (but not yet deallocated) -/// * `E` is the reference counter (last one for sum/subtraction efficiency). The max value (the -/// one with every bit set to 1) is reserved and should not be used +/// * `C` is `1` when metadata has been allocated, `0` otherwise +/// * `D` is `1` when the element inside `CcBox` has already been finalized, `0` otherwise +/// * `E` is the reference counter. The max value (the one with every bit set to 1) is reserved and should not be used #[derive(Clone, Debug)] -#[repr(transparent)] pub(crate) struct CounterMarker { - counter: Cell, + tracing_counter: Cell, + counter: Cell, } pub(crate) struct OverflowError; @@ -51,6 +49,7 @@ impl CounterMarker { #[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 { @@ -94,7 +93,7 @@ impl CounterMarker { Err(OverflowError) } else { // Increment trace_counter and not counter - self.counter.set(self.counter.get() + (1u32 << 14)); + self.tracing_counter.set(self.tracing_counter.get() + 1); Ok(()) } } @@ -108,21 +107,21 @@ impl CounterMarker { Err(OverflowError) } else { // Decrement trace_counter and not counter - self.counter.set(self.counter.get() - (1u32 << 14)); + self.tracing_counter.set(self.tracing_counter.get() - 1); Ok(()) } } #[inline] - pub(crate) fn counter(&self) -> u32 { + pub(crate) fn counter(&self) -> u16 { let rc = self.counter.get() & COUNTER_MASK; debug_assert!(rc != COUNTER_MASK); // Check for reserved value rc } #[inline] - pub(crate) fn tracing_counter(&self) -> u32 { - let tc = (self.counter.get() & TRACING_COUNTER_MASK) >> 14; + pub(crate) fn tracing_counter(&self) -> u16 { + let tc = self.tracing_counter.get() & COUNTER_MASK; debug_assert!(tc != COUNTER_MASK); // Check for reserved value tc } @@ -130,92 +129,92 @@ impl CounterMarker { #[inline] pub(crate) fn reset_tracing_counter(&self) { debug_assert!(self.tracing_counter() != COUNTER_MASK); // Check for reserved value - self.counter.set(self.counter.get() & !TRACING_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) == 0u32 + (self.counter.get() & FINALIZED_MASK) == 0u16 } #[cfg(feature = "finalization")] #[inline] pub(crate) fn set_finalized(&self, finalized: bool) { - self.set_bits(finalized, FINALIZED_MASK); + 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() & METADATA_MASK) == METADATA_MASK + (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(allocated_for_metadata, METADATA_MASK); + Self::set_bits(&self.counter, allocated_for_metadata, FIRST_BIT_MASK); } #[cfg(feature = "weak-ptrs")] #[inline] pub(crate) fn is_dropped(&self) -> bool { - (self.counter.get() & TRACING_COUNTER_MASK) == TRACING_COUNTER_MASK + (self.tracing_counter.get() & COUNTER_MASK) == COUNTER_MASK } #[cfg(feature = "weak-ptrs")] #[inline] pub(crate) fn set_dropped(&self, dropped: bool) { - self.set_bits(dropped, TRACING_COUNTER_MASK); + Self::set_bits(&self.tracing_counter, dropped, COUNTER_MASK); } #[inline] pub(crate) fn is_not_marked(&self) -> bool { // true if (self.counter & BITS_MASK) is equal to 01 or 00, // so if the first bit is 0 - (self.counter.get() & FIRST_BIT_MASK) == 0u32 + (self.tracing_counter.get() & FIRST_BIT_MASK) == 0u16 } #[inline] pub(crate) fn is_in_possible_cycles(&self) -> bool { - (self.counter.get() & BITS_MASK) == IN_POSSIBLE_CYCLES + (self.tracing_counter.get() & BITS_MASK) == IN_POSSIBLE_CYCLES } #[inline] pub(crate) fn is_in_list(&self) -> bool { - (self.counter.get() & BITS_MASK) == IN_LIST + (self.tracing_counter.get() & BITS_MASK) == IN_LIST } #[inline] pub(crate) fn _is_in_queue(&self) -> bool { - (self.counter.get() & BITS_MASK) == IN_QUEUE + (self.tracing_counter.get() & BITS_MASK) == IN_QUEUE } #[inline] pub(crate) fn is_in_list_or_queue(&self) -> bool { // true if (self.counter & BITS_MASK) is equal to 10 or 11, // so if the first bit is 1 - (self.counter.get() & FIRST_BIT_MASK) == FIRST_BIT_MASK + (self.tracing_counter.get() & FIRST_BIT_MASK) == FIRST_BIT_MASK } #[inline] pub(crate) fn mark(&self, new_mark: Mark) { - self.counter.set((self.counter.get() & !BITS_MASK) | (new_mark as u32)); + 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(&self, value: bool, mask: u32) { + fn set_bits(cell: &Cell, value: bool, mask: u16) { if value { - self.counter.set(self.counter.get() | mask); + cell.set(cell.get() | mask); } else { - self.counter.set(self.counter.get() & !mask); + cell.set(cell.get() & !mask); } } } #[derive(Copy, Clone, Debug)] -#[repr(u32)] +#[repr(u16)] pub(crate) enum Mark { NonMarked = NON_MARKED, PossibleCycles = IN_POSSIBLE_CYCLES, diff --git a/src/weak/mod.rs b/src/weak/mod.rs index 64ac7a7..361a1b1 100644 --- a/src/weak/mod.rs +++ b/src/weak/mod.rs @@ -119,7 +119,7 @@ impl Weak { ) { 0 } else { - counter + counter as u32 } } else { 0