From a2f1a559366ced2f1fa74cf86e9b8591ff9cd60f Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Thu, 4 May 2023 08:27:48 -0500 Subject: [PATCH 1/3] added failing test --- src/atomic.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/atomic.rs b/src/atomic.rs index ddfba97..54af766 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -483,4 +483,10 @@ mod atomic_set_test { set.clear(); assert_eq!((&set).iter().count(), 0); } + + #[test] + fn debug() { + let bitset = AtomicBitSet::default(); + println!("debug = {:?}", bitset); + } } From 199f0330fb46cd3202bddea7a69c060fc7d26560 Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Thu, 4 May 2023 08:50:19 -0500 Subject: [PATCH 2/3] Custom Debug for AtomicBitSet --- src/atomic.rs | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/atomic.rs b/src/atomic.rs index 54af766..d423a0e 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -26,7 +26,7 @@ use {BitSetLike, DrainableBitSet}; /// clearing of bits. /// /// [`BitSet`]: ../struct.BitSet.html -#[derive(Debug)] +// #[derive(Debug)] pub struct AtomicBitSet { layer3: AtomicUsize, layer2: Vec, @@ -201,6 +201,26 @@ impl Default for AtomicBitSet { } } +impl Debug for AtomicBitSet { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let mut s = f.debug_struct("AtomicBitSet"); + + s.field( + "layer1", + &self + .layer1 + .iter() + .enumerate() + .filter(|(_, v)| !v.is_empty()) + .collect::>(), + ); + s.field("layer2", &self.layer2); + s.field("layer3", &self.layer3); + + s.finish() + } +} + struct OnceAtom { inner: AtomicPtr<[AtomicUsize; 1 << BITS]>, marker: PhantomData>>, @@ -285,6 +305,11 @@ impl AtomicBlock { } } + /// Returns true if the block has an empty mask + fn is_empty(&self) -> bool { + self.mask.fetch_or(0, Ordering::Relaxed) == 0 + } + fn add(&self, id: Index) -> bool { let (i, m) = (id.row(SHIFT1), id.mask(SHIFT0)); let old = self.atom.get_or_init()[i].fetch_or(m, Ordering::Relaxed); @@ -328,10 +353,12 @@ impl AtomicBlock { impl Debug for AtomicBlock { fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> { - f.debug_struct("AtomicBlock") - .field("mask", &self.mask) - .field("atom", &self.atom.get().unwrap().iter()) - .finish() + let mut s = f.debug_struct("AtomicBlock"); + s.field("mask", &self.mask); + if let Some(atom) = self.atom.get() { + s.field("atom", &atom.iter()); + } + s.finish() } } From eccdc19d9ec693d229aea31476baff8cc4dd49db Mon Sep 17 00:00:00 2001 From: Funnisimo Date: Thu, 4 May 2023 09:12:01 -0500 Subject: [PATCH 3/3] AtomicBitSet Debug outputs iter() --- src/atomic.rs | 53 ++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/atomic.rs b/src/atomic.rs index d423a0e..18141cb 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -15,14 +15,14 @@ use {BitSetLike, DrainableBitSet}; /// without unique ownership (given that the set is big enough). /// Removing elements does require unique ownership as an effect /// of the hierarchy it holds. Worst case multiple writers set the -/// same bit twice (but only is told they set it). +/// same bit twice (but only one is told they set it). /// /// It is possible to atomically remove from the set, but not at the /// same time as atomically adding. This is because there is no way /// to know if layer 1-3 would be left in a consistent state if they are /// being cleared and set at the same time. /// -/// `AtromicBitSet` resolves this race by disallowing atomic +/// `AtomicBitSet` resolves this race by disallowing atomic /// clearing of bits. /// /// [`BitSet`]: ../struct.BitSet.html @@ -203,21 +203,8 @@ impl Default for AtomicBitSet { impl Debug for AtomicBitSet { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let mut s = f.debug_struct("AtomicBitSet"); - - s.field( - "layer1", - &self - .layer1 - .iter() - .enumerate() - .filter(|(_, v)| !v.is_empty()) - .collect::>(), - ); - s.field("layer2", &self.layer2); - s.field("layer3", &self.layer3); - - s.finish() + write!(f, "AtomicBitSet")?; + f.debug_list().entries(self.iter()).finish() } } @@ -305,11 +292,6 @@ impl AtomicBlock { } } - /// Returns true if the block has an empty mask - fn is_empty(&self) -> bool { - self.mask.fetch_or(0, Ordering::Relaxed) == 0 - } - fn add(&self, id: Index) -> bool { let (i, m) = (id.row(SHIFT1), id.mask(SHIFT0)); let old = self.atom.get_or_init()[i].fetch_or(m, Ordering::Relaxed); @@ -356,7 +338,17 @@ impl Debug for AtomicBlock { let mut s = f.debug_struct("AtomicBlock"); s.field("mask", &self.mask); if let Some(atom) = self.atom.get() { - s.field("atom", &atom.iter()); + s.field( + "atom", + &atom + .iter() + .enumerate() + .filter_map(|(idx, v)| match v.fetch_or(0, Ordering::Relaxed) { + 0 => None, + x => Some((idx, x)), + }) + .collect::>(), + ); } s.finish() } @@ -513,7 +505,20 @@ mod atomic_set_test { #[test] fn debug() { - let bitset = AtomicBitSet::default(); + let mut bitset = AtomicBitSet::default(); + println!("debug = {:?}", bitset); + + bitset.add(5); + bitset.add(127194); + + println!("debug = {:?}", bitset); + + bitset.remove(127194); + + println!("debug = {:?}", bitset); + + bitset.remove(5); + println!("debug = {:?}", bitset); } }