@@ -66,6 +66,20 @@ pub mod details {
66
66
pub type BitsetElement = AtomicU8 ;
67
67
const BITSET_ELEMENT_BITSIZE : usize = core:: mem:: size_of :: < BitsetElement > ( ) * 8 ;
68
68
69
+ struct Id {
70
+ index : usize ,
71
+ bit : u8 ,
72
+ }
73
+
74
+ impl Id {
75
+ fn new ( value : usize ) -> Id {
76
+ Self {
77
+ index : value / BITSET_ELEMENT_BITSIZE ,
78
+ bit : ( value % BITSET_ELEMENT_BITSIZE ) as u8 ,
79
+ }
80
+ }
81
+ }
82
+
69
83
#[ derive( Debug ) ]
70
84
#[ repr( C ) ]
71
85
pub struct BitSet < PointerType : PointerTrait < BitsetElement > > {
@@ -191,20 +205,17 @@ pub mod details {
191
205
) ;
192
206
}
193
207
194
- fn set_bit ( & self , id : usize ) -> bool {
195
- let index = id / BITSET_ELEMENT_BITSIZE ;
196
- let bit = id % BITSET_ELEMENT_BITSIZE ;
197
-
198
- let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( index) ) } ;
208
+ fn set_bit ( & self , id : Id ) -> bool {
209
+ let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( id. index ) ) } ;
199
210
let mut current = data_ref. load ( Ordering :: Relaxed ) ;
200
- let bit = 1 << bit;
211
+ let mask = 1 << id . bit ;
201
212
202
213
loop {
203
- if current & bit != 0 {
214
+ if current & mask != 0 {
204
215
return false ;
205
216
}
206
217
207
- let current_with_bit = current | bit ;
218
+ let current_with_bit = current | mask ;
208
219
209
220
match data_ref. compare_exchange (
210
221
current,
@@ -221,24 +232,21 @@ pub mod details {
221
232
}
222
233
}
223
234
224
- fn clear_bit ( & self , id : usize ) -> bool {
225
- let index = id / BITSET_ELEMENT_BITSIZE ;
226
- let bit = id % BITSET_ELEMENT_BITSIZE ;
227
-
228
- let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( index) ) } ;
235
+ fn clear_bit ( & self , id : Id ) -> bool {
236
+ let data_ref = unsafe { & ( * self . data_ptr . as_ptr ( ) . add ( id. index ) ) } ;
229
237
let mut current = data_ref. load ( Ordering :: Relaxed ) ;
230
- let bit = 1 << bit;
238
+ let mask = 1 << id . bit ;
231
239
232
240
loop {
233
- if current & bit == 0 {
241
+ if current & mask == 0 {
234
242
return false ;
235
243
}
236
244
237
- let current_with_bit = current & !bit ;
245
+ let current_with_cleared_bit = current & !mask ;
238
246
239
247
match data_ref. compare_exchange (
240
248
current,
241
- current_with_bit ,
249
+ current_with_cleared_bit ,
242
250
Ordering :: Relaxed ,
243
251
Ordering :: Relaxed ,
244
252
) {
@@ -262,7 +270,7 @@ pub mod details {
262
270
id
263
271
) ;
264
272
265
- self . set_bit ( id )
273
+ self . set_bit ( Id :: new ( id ) )
266
274
}
267
275
268
276
/// Resets the next set bit and returns the bit index. If no bit was set it returns
@@ -273,14 +281,11 @@ pub mod details {
273
281
return None ;
274
282
}
275
283
276
- let mut current_position = self . reset_position . load ( Ordering :: Relaxed ) ;
277
- for _ in 0 ..self . capacity {
278
- current_position = ( current_position + 1 ) % self . capacity ;
279
-
280
- if self . clear_bit ( current_position) {
281
- self . reset_position
282
- . store ( current_position, Ordering :: Relaxed ) ;
283
- return Some ( current_position) ;
284
+ let current_position = self . reset_position . load ( Ordering :: Relaxed ) ;
285
+ for pos in ( current_position..self . capacity ) . chain ( 0 ..current_position) {
286
+ if self . clear_bit ( Id :: new ( pos) ) {
287
+ self . reset_position . store ( pos + 1 , Ordering :: Relaxed ) ;
288
+ return Some ( pos) ;
284
289
}
285
290
}
286
291
@@ -295,15 +300,15 @@ pub mod details {
295
300
for i in 0 ..self . array_capacity {
296
301
let value = unsafe { ( * self . data_ptr . as_ptr ( ) . add ( i) ) . swap ( 0 , Ordering :: Relaxed ) } ;
297
302
let mut counter = 0 ;
303
+ let main_index = i * BITSET_ELEMENT_BITSIZE ;
298
304
for b in 0 ..BITSET_ELEMENT_BITSIZE {
299
- let main_index = i * BITSET_ELEMENT_BITSIZE ;
300
305
if value & ( 1 << b) != 0 {
301
306
callback ( main_index + b) ;
302
307
counter += 1 ;
303
308
}
304
309
}
305
310
306
- if self . active_bits . fetch_sub ( counter, Ordering :: Relaxed ) == 1 {
311
+ if self . active_bits . fetch_sub ( counter, Ordering :: Relaxed ) == counter {
307
312
return ;
308
313
}
309
314
}
0 commit comments