index_set/
shared_bitset.rs

1use crate::*;
2
3/// A trait for updating values in a shared bit-set.
4pub trait SharedBitSet<T> {
5    /// Clears the set
6    ///
7    /// # Example
8    ///
9    /// ```rust
10    /// use index_set::{SharedBitSet, BitSet};
11    /// use std::sync::atomic::AtomicU32;
12    ///
13    /// let mut bitset: [AtomicU32; 4] = Default::default();
14    /// bitset.insert(0);
15    /// assert!(!BitSet::is_empty(&bitset[..]));
16    ///
17    /// bitset.clear();
18    /// assert!(BitSet::is_empty(&bitset[..]));
19    /// ```
20    fn clear(&self);
21
22    /// Inserts the index into the set
23    /// Returns `true` if the index was not already set
24    ///
25    /// # Example
26    ///
27    /// ```rust
28    /// use index_set::{SharedBitSet, BitSet};
29    /// use std::sync::atomic::AtomicU32;
30    ///
31    /// let mut bitset: [AtomicU32; 4] = Default::default();
32    /// bitset.insert(0);
33    /// assert_eq!(bitset.has(0), true);
34    /// ```
35    fn insert(&self, index: T) -> Option<bool>;
36
37    /// Removes the index from the set
38    /// Returns `true` if the index was set.
39    ///
40    /// # Example
41    ///
42    /// ```rust
43    /// use index_set::{SharedBitSet, BitSet};
44    /// use std::sync::atomic::AtomicU32;
45    ///
46    /// let mut bitset: [AtomicU32; 4] = Default::default();
47    /// bitset.insert(42);
48    /// assert_eq!(bitset.has(42), true);
49    ///
50    /// bitset.remove(42);
51    /// assert_eq!(bitset.has(42), false);
52    /// ```
53    fn remove(&self, index: T) -> Option<bool>;
54}
55
56impl<Set, T> SharedBitSet<T> for &Set
57where
58    Set: SharedBitSet<T> + ?Sized,
59{
60    #[inline]
61    fn clear(&self) {
62        SharedBitSet::clear(*self);
63    }
64
65    #[inline]
66    fn insert(&self, index: T) -> Option<bool> {
67        SharedBitSet::insert(*self, index)
68    }
69
70    #[inline]
71    fn remove(&self, index: T) -> Option<bool> {
72        SharedBitSet::remove(*self, index)
73    }
74}
75
76macro_rules! impl_shared_bit_set {
77    [$($ty:tt for $target: ty)*] => {$(
78        impl SharedBitSet<$ty> for [$target] {
79            fn clear(&self) {
80                for slot in self.iter() {
81                    slot.store(0, Ordering::Release);
82                }
83            }
84
85            #[inline]
86            fn insert(&self, index: $ty) -> Option<bool> {
87                let slot_idx = usize::try_from(index / $ty::BITS as $ty).ok()?;
88                let mask = 1 << (index % $ty::BITS as $ty);
89
90                let slot = self
91                    .get(slot_idx)?
92                    .fetch_or(mask, Ordering::Release);
93
94                Some(slot & mask != 0)
95            }
96
97            #[inline]
98            fn remove(&self, index: $ty) -> Option<bool> {
99                let slot_idx = usize::try_from(index / $ty::BITS as $ty).ok()?;
100                let mask = 1 << (index % $ty::BITS as $ty);
101
102                let slot = self
103                    .get(slot_idx)?
104                    .fetch_and(!mask, Ordering::Release);
105
106                Some(slot & mask != 0)
107            }
108        }
109    )*};
110}
111
112impl_shared_bit_set! {
113    u32 for AtomicU32
114    u64 for AtomicU64
115    usize for AtomicUsize
116}