@@ -61,6 +61,8 @@ pub type BitSet = details::BitSet<OwningPointer<BitsetElement>>;
61
61
pub type RelocatableBitSet = details:: BitSet < RelocatablePointer < BitsetElement > > ;
62
62
63
63
pub mod details {
64
+ use std:: sync:: atomic:: AtomicUsize ;
65
+
64
66
use super :: * ;
65
67
66
68
#[ derive( Debug ) ]
@@ -69,6 +71,7 @@ pub mod details {
69
71
data_ptr : PointerType ,
70
72
capacity : usize ,
71
73
array_capacity : usize ,
74
+ reset_position : AtomicUsize ,
72
75
is_memory_initialized : AtomicBool ,
73
76
}
74
77
@@ -95,6 +98,7 @@ pub mod details {
95
98
capacity,
96
99
array_capacity,
97
100
is_memory_initialized : AtomicBool :: new ( true ) ,
101
+ reset_position : AtomicUsize :: new ( 0 ) ,
98
102
}
99
103
}
100
104
}
@@ -106,6 +110,7 @@ pub mod details {
106
110
capacity,
107
111
array_capacity : Self :: array_capacity ( capacity) ,
108
112
is_memory_initialized : AtomicBool :: new ( false ) ,
113
+ reset_position : AtomicUsize :: new ( 0 ) ,
109
114
}
110
115
}
111
116
@@ -152,6 +157,7 @@ pub mod details {
152
157
capacity,
153
158
array_capacity : Self :: array_capacity ( capacity) ,
154
159
is_memory_initialized : AtomicBool :: new ( true ) ,
160
+ reset_position : AtomicUsize :: new ( 0 ) ,
155
161
}
156
162
}
157
163
}
@@ -180,7 +186,10 @@ pub mod details {
180
186
) ;
181
187
}
182
188
183
- fn set_bit ( & self , index : usize , bit : usize ) -> bool {
189
+ fn set_bit ( & self , id : usize ) -> bool {
190
+ let index = id / BITSET_ELEMENT_BITSIZE ;
191
+ let bit = id % BITSET_ELEMENT_BITSIZE ;
192
+
184
193
let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( index) ) } ;
185
194
let mut current = data_ref. load ( Ordering :: Relaxed ) ;
186
195
let bit = 1 << bit;
@@ -204,7 +213,36 @@ pub mod details {
204
213
}
205
214
}
206
215
216
+ fn clear_bit ( & self , id : usize ) -> bool {
217
+ let index = id / BITSET_ELEMENT_BITSIZE ;
218
+ let bit = id % BITSET_ELEMENT_BITSIZE ;
219
+
220
+ let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( index) ) } ;
221
+ let mut current = data_ref. load ( Ordering :: Relaxed ) ;
222
+ let bit = 1 << bit;
223
+
224
+ loop {
225
+ if current & bit == 0 {
226
+ return false ;
227
+ }
228
+
229
+ let current_with_bit = current & !bit;
230
+
231
+ match data_ref. compare_exchange (
232
+ current,
233
+ current_with_bit,
234
+ Ordering :: Relaxed ,
235
+ Ordering :: Relaxed ,
236
+ ) {
237
+ Ok ( _) => return true ,
238
+ Err ( v) => current = v,
239
+ }
240
+ }
241
+ }
242
+
207
243
/// Sets a bit in the BitSet
244
+ /// If the bit was successfully set it returns true, if the bit was already set it
245
+ /// returns false.
208
246
pub fn set ( & self , id : usize ) -> bool {
209
247
self . verify_init ( "set" ) ;
210
248
debug_assert ! (
@@ -213,14 +251,29 @@ pub mod details {
213
251
id
214
252
) ;
215
253
216
- let bitset_index = id / BITSET_ELEMENT_BITSIZE ;
217
- let bit = id % BITSET_ELEMENT_BITSIZE ;
218
- self . set_bit ( bitset_index, bit)
254
+ self . set_bit ( id)
255
+ }
256
+
257
+ /// Resets the next set bit and returns the bit index. If no bit was set it returns
258
+ /// [`None`].
259
+ pub fn reset_next ( & self ) -> Option < usize > {
260
+ let mut current_position = self . reset_position . load ( Ordering :: Relaxed ) ;
261
+ for _ in 0 ..self . capacity {
262
+ current_position = ( current_position + 1 ) % self . capacity ;
263
+
264
+ if self . clear_bit ( current_position) {
265
+ self . reset_position
266
+ . store ( current_position, Ordering :: Relaxed ) ;
267
+ return Some ( current_position) ;
268
+ }
269
+ }
270
+
271
+ None
219
272
}
220
273
221
274
/// Reset every set bit in the BitSet and call the provided callback for every bit that
222
- /// was set.
223
- pub fn reset < F : FnMut ( usize ) > ( & self , mut callback : F ) {
275
+ /// was set. This is the most efficient way to acquire all bits that were set.
276
+ pub fn reset_all < F : FnMut ( usize ) > ( & self , mut callback : F ) {
224
277
self . verify_init ( "set" ) ;
225
278
for i in 0 ..self . array_capacity {
226
279
let value = unsafe { ( * self . data_ptr . as_ptr ( ) . add ( i) ) . swap ( 0 , Ordering :: Relaxed ) } ;
@@ -282,7 +335,13 @@ impl<const CAPACITY: usize> FixedSizeBitSet<CAPACITY> {
282
335
283
336
/// Reset every set bit in the BitSet and call the provided callback for every bit that
284
337
/// was set.
285
- pub fn reset < F : FnMut ( usize ) > ( & self , callback : F ) {
286
- self . bitset . reset ( callback)
338
+ pub fn reset_next ( & self ) -> Option < usize > {
339
+ self . bitset . reset_next ( )
340
+ }
341
+
342
+ /// Reset every set bit in the BitSet and call the provided callback for every bit that
343
+ /// was set.
344
+ pub fn reset_all < F : FnMut ( usize ) > ( & self , callback : F ) {
345
+ self . bitset . reset_all ( callback)
287
346
}
288
347
}
0 commit comments