stable_vec/core/bitvec.rs
1use ::core::{
2 fmt,
3 mem::{align_of, size_of},
4 ptr::{self, NonNull},
5};
6
7use alloc::alloc::{alloc, alloc_zeroed, dealloc, handle_alloc_error, realloc, Layout};
8
9use super::Core;
10
11
12/// A `Core` implementation that is conceptually a `BitVec` and a `Vec<T>`.
13///
14/// This is the default core as it has quite a few advantages. For one, it does
15/// not waste memory due to padding. The information about whether a slot is
16/// filled or not is stored in a `BitVec` and thus only takes one bit per slot.
17///
18/// Using a `BitVec` has another important advantage: iterating over the
19/// indices of a stable vector (i.e. without touching the actual data) is very
20/// cache-friendly. This is due to the dense packing of information. It's also
21/// possible to very quickly scan the bit vector in order to find filled/empty
22/// slots.
23///
24/// However, this core implementation has disadvantages, too. It manages two
25/// allocations which means that reallocating (growing or shrinking) has to
26/// perform two allocations with the underlying memory allocator. Potentially
27/// more important is the decrease of cache-friendliness when accessing
28/// elements at random. Because in the worst case, this means that each element
29/// access results in two cache-misses instead of only one.
30///
31/// For most use cases, this is a good choice. That's why it's default.
32pub struct BitVecCore<T> {
33 /// This is the memory that stores the actual slots/elements. If a slot is
34 /// empty, the memory at that index is undefined.
35 elem_ptr: NonNull<T>,
36
37 /// Stores whether or not slots are filled (1) or empty (0). Stores one bit
38 /// per slot. Is stored as `usize` instead of `u8` to potentially improve
39 /// performance when finding a hole or counting the elements.
40 bit_ptr: NonNull<usize>,
41
42 /// The capacity: the length of the `elem_ptr` buffer. Corresponse to the
43 /// `cap` of the `Core` definition.
44 cap: usize,
45
46 /// The `len`: corresponse to the `len` of the `Core` definition.
47 len: usize,
48}
49
50const BITS_PER_USIZE: usize = size_of::<usize>() * 8;
51
52impl<T> BitVecCore<T> {
53 /// Deallocates both pointers and sets `cap` to 0.
54 ///
55 /// Note that elements which are still stored in filled slots are **not**
56 /// dropped but simply leaked. So all slots should be empty when calling
57 /// this, unless leaking is intended (see the `Drop` impl below).
58 ///
59 /// # Formal
60 ///
61 /// **Preconditions**:
62 /// - `self.len == 0`
63 unsafe fn dealloc(&mut self) {
64 if self.cap != 0 {
65 if size_of::<T>() != 0 {
66 dealloc(self.elem_ptr.as_ptr() as *mut _, self.old_elem_layout());
67 }
68
69 dealloc(self.bit_ptr.as_ptr() as *mut _, self.old_bit_layout());
70 self.cap = 0;
71 }
72 }
73
74 /// Returns the layout that was used for the last allocation of `elem_ptr`.
75 /// `self.cap` must not be 0 and `T` must not be a ZST, or else this
76 /// method's behavior is undefined.
77 unsafe fn old_elem_layout(&self) -> Layout {
78 Layout::from_size_align_unchecked(
79 // This can't overflow due to being previously allocated.
80 self.cap * size_of::<T>(),
81 align_of::<T>(),
82 )
83 }
84
85 /// Returns the layout that was used for the last allocation of `bit_ptr`.
86 /// `self.cap` must not be 0 or else this method's behavior is undefined.
87 unsafe fn old_bit_layout(&self) -> Layout {
88 Layout::from_size_align_unchecked(
89 size_of::<usize>() * num_usizes_for(self.cap),
90 align_of::<usize>(),
91 )
92 }
93}
94
95impl<T> Core<T> for BitVecCore<T> {
96 fn new() -> Self {
97 Self {
98 elem_ptr: NonNull::dangling(),
99 bit_ptr: NonNull::dangling(),
100 cap: 0,
101 len: 0,
102 }
103 }
104
105 fn len(&self) -> usize {
106 self.len
107 }
108
109 unsafe fn set_len(&mut self, new_len: usize) {
110 debug_assert!(new_len <= self.cap());
111 // Other precondition is too expensive to test, even in debug:
112 // ∀ i in `new_len..self.cap()` ⇒ `self.has_element_at(i) == false`
113
114 self.len = new_len;
115
116 // The formal requirements of this method hold:
117 //
118 // **Invariants**:
119 // - *slot data* -> trivially holds, we do not touch that
120 // - `len ≤ cap` -> that's a precondition
121 //
122 // **Postconditons**:
123 // - `self.len() == new_len`: trivially holds
124 }
125
126 fn cap(&self) -> usize {
127 self.cap
128 }
129
130 #[inline(never)]
131 #[cold]
132 unsafe fn realloc(&mut self, new_cap: usize) {
133 debug_assert!(new_cap >= self.len());
134 debug_assert!(new_cap <= isize::max_value() as usize);
135
136 #[inline(never)]
137 #[cold]
138 fn capacity_overflow() -> ! {
139 panic!("capacity overflow in `stable_vec::BitVecCore::realloc` (attempt \
140 to allocate more than `isize::MAX` bytes");
141 }
142
143 // Handle special case
144 if new_cap == 0 {
145 // Due to preconditions, we know that `self.len == 0` and that in
146 // turn tells us that there aren't any filled slots. So we can just
147 // deallocate the memory.
148 self.dealloc();
149 return;
150 }
151
152
153 // ----- (Re)allocate element memory ---------------------------------
154
155 // We only have to allocate if our size are not zero-sized. Else, we
156 // just don't do anything.
157 if size_of::<T>() != 0 {
158 // Get the new number of bytes for the allocation and create the
159 // memory layout.
160 let size = new_cap.checked_mul(size_of::<T>())
161 .unwrap_or_else(|| capacity_overflow());
162 let new_elem_layout = Layout::from_size_align(size, align_of::<T>())
163 .unwrap_or_else(|_| capacity_overflow());
164
165 // (Re)allocate memory.
166 let ptr = if self.cap == 0 {
167 alloc(new_elem_layout)
168 } else {
169 realloc(self.elem_ptr.as_ptr() as *mut _, self.old_elem_layout(), size)
170 };
171
172 // If the element allocation failed, we quit the program with an
173 // OOM error.
174 if ptr.is_null() {
175 handle_alloc_error(new_elem_layout);
176 }
177
178 // We already overwrite the pointer here. It is not read/changed
179 // anywhere else in this function.
180 self.elem_ptr = NonNull::new_unchecked(ptr as *mut _);
181 };
182
183
184 // ----- (Re)allocate bitvec memory ----------------------------------
185 {
186 // Get the new number of required bytes for the allocation and
187 // create the memory layout.
188 let size = size_of::<usize>() * num_usizes_for(new_cap);
189 let new_bit_layout = Layout::from_size_align_unchecked(size, align_of::<usize>());
190
191 // (Re)allocate memory.
192 let ptr = if self.cap == 0 {
193 alloc_zeroed(new_bit_layout)
194 } else {
195 realloc(self.bit_ptr.as_ptr() as *mut _, self.old_bit_layout(), size)
196 };
197 let ptr = ptr as *mut usize;
198
199 // If the element allocation failed, we quit the program with an
200 // OOM error.
201 if ptr.is_null() {
202 handle_alloc_error(new_bit_layout);
203 }
204
205 // If we reallocated, the new memory is not necessarily zeroed, so
206 // we need to do it. TODO: if `alloc` offers a `realloc_zeroed`
207 // in the future, we should use that.
208 if self.cap != 0 {
209 let initialized_usizes = num_usizes_for(self.cap);
210 let new_usizes = num_usizes_for(new_cap);
211 if new_usizes > initialized_usizes {
212 ptr::write_bytes(
213 ptr.add(initialized_usizes),
214 0,
215 new_usizes - initialized_usizes,
216 );
217 }
218 }
219
220 self.bit_ptr = NonNull::new_unchecked(ptr as *mut _);
221 }
222
223 self.cap = new_cap;
224
225 // All formal requirements are met now:
226 //
227 // **Invariants**:
228 // - *slot data*: by using `realloc` if `self.cap != 0`, the slot data
229 // (including deleted-flag) was correctly copied.
230 // - `self.len()`: indeed didn't change
231 //
232 // **Postconditons**:
233 // - `self.cap() == new_cap`: trivially holds due to last line.
234 }
235
236 unsafe fn has_element_at(&self, idx: usize) -> bool {
237 debug_assert!(idx < self.cap());
238
239 // The divisions will be turned into shift and 'and'-instructions.
240 let usize_pos = idx / BITS_PER_USIZE;
241 let bit_pos = idx % BITS_PER_USIZE;
242
243 let block = *self.bit_ptr.as_ptr().add(usize_pos);
244 ((block >> bit_pos) & 0b1) != 0
245 }
246
247 unsafe fn insert_at(&mut self, idx: usize, elem: T) {
248 debug_assert!(idx < self.cap());
249 debug_assert!(self.has_element_at(idx) == false);
250
251 // We first write the value and then update the bitvector to avoid
252 // potential double drops if a random panic appears.
253 ptr::write(self.elem_ptr.as_ptr().add(idx), elem);
254
255 let usize_pos = idx / BITS_PER_USIZE;
256 let bit_pos = idx % BITS_PER_USIZE;
257
258 let mask = 1 << bit_pos;
259 *self.bit_ptr.as_ptr().add(usize_pos) |= mask;
260 }
261
262 unsafe fn remove_at(&mut self, idx: usize) -> T {
263 debug_assert!(idx < self.cap());
264 debug_assert!(self.has_element_at(idx));
265
266 // We first mark the value as deleted and then read the value.
267 // Otherwise, a random panic could lead to a double drop.
268 let usize_pos = idx / BITS_PER_USIZE;
269 let bit_pos = idx % BITS_PER_USIZE;
270
271 let mask = !(1 << bit_pos);
272 *self.bit_ptr.as_ptr().add(usize_pos) &= mask;
273
274 ptr::read(self.elem_ptr.as_ptr().add(idx))
275 }
276
277 unsafe fn get_unchecked(&self, idx: usize) -> &T {
278 debug_assert!(idx < self.cap());
279 debug_assert!(self.has_element_at(idx));
280
281 // The preconditions of this function guarantees us that all
282 // preconditions for `add` are met and that we can safely dereference
283 // the pointer.
284 &*self.elem_ptr.as_ptr().add(idx)
285 }
286
287 unsafe fn get_unchecked_mut(&mut self, idx: usize) -> &mut T {
288 debug_assert!(idx < self.cap());
289 debug_assert!(self.has_element_at(idx));
290
291 // The preconditions of this function guarantees us that all
292 // preconditions for `add` are met and that we can safely dereference
293 // the pointer.
294 &mut *self.elem_ptr.as_ptr().add(idx)
295 }
296
297 fn clear(&mut self) {
298 unsafe {
299 // Remove each element via `remove_at`, which clears the occupancy bit
300 // *before* taking the value out, so a panicking `Drop` can't leave a
301 // slot marked occupied for `BitVecCore::drop` -> `clear` to revisit.
302 for idx in 0..self.len {
303 if self.has_element_at(idx) {
304 drop(self.remove_at(idx));
305 }
306 }
307 self.len = 0;
308 }
309 }
310
311 // TODO: maybe override `{next|prev}_{hole|index}_from` for performance? In
312 // principle we could scan the bitvector very quickly with specialized
313 // instructions. Needs benchmarking.
314
315 unsafe fn swap(&mut self, a: usize, b: usize) {
316 // Swapping the bits is a bit annoying. To avoid branches we first xor
317 // both previous bits.
318 let a_existed = self.has_element_at(a);
319 let b_existed = self.has_element_at(b);
320
321 // `swap_bit` is 0 if both slots were empty of filled, and 1 if only
322 // only one slot was empty. That also means the mask is 0 if both were
323 // empty/filled before, otherwise the mask has one bit set. We xor with
324 // this mask, meaning that we will flip the corresponding bit.
325 let swap_bit = (a_existed ^ b_existed) as usize;
326
327 // For a
328 let usize_pos = a / BITS_PER_USIZE;
329 let bit_pos = a % BITS_PER_USIZE;
330 let mask = swap_bit << bit_pos;
331 *self.bit_ptr.as_ptr().add(usize_pos) ^= mask;
332
333 // For b
334 let usize_pos = b / BITS_PER_USIZE;
335 let bit_pos = b % BITS_PER_USIZE;
336 let mask = swap_bit << bit_pos;
337 *self.bit_ptr.as_ptr().add(usize_pos) ^= mask;
338
339 // Finally swap the actual elements
340 ptr::swap(
341 self.elem_ptr.as_ptr().add(a),
342 self.elem_ptr.as_ptr().add(b),
343 );
344 }
345}
346
347impl<T> Drop for BitVecCore<T> {
348 fn drop(&mut self) {
349 /// Deallocates the memory of the core in its own `drop`, so that this
350 /// also happens when dropping an element panics.
351 struct DeallocGuard<'a, T>(&'a mut BitVecCore<T>);
352
353 impl<T> Drop for DeallocGuard<'_, T> {
354 fn drop(&mut self) {
355 unsafe {
356 self.0.len = 0;
357 self.0.dealloc();
358 }
359 }
360 }
361
362 // Dropping the elements can panic, so the deallocation is done by the
363 // guard: its `drop` runs in both cases. We then simply don't drop the
364 // remaining elements, as we don't want to risk a double-drop process
365 // abort. But while the elements are leaked, we at least dealloc our
366 // own memory.
367 let guard = DeallocGuard(self);
368 guard.0.clear();
369 }
370}
371
372impl<T: Clone> Clone for BitVecCore<T> {
373 fn clone(&self) -> Self {
374 let mut out = Self::new();
375
376 if self.cap != 0 {
377 unsafe {
378 out.realloc(self.cap);
379
380 // The length is set before inserting anything: if a `clone`
381 // below panics, `out` is dropped and it has to be able to see
382 // the elements that were already inserted (otherwise those
383 // would be leaked). All slots of `out` are still empty, so
384 // this is fine.
385 out.set_len(self.len);
386
387 // Clone all elements over. We use `insert_at` instead of
388 // copying the whole bitvec at the end, as it sets the
389 // "filled" bit of each element right away. That way, `out` is
390 // in a valid state at all times, even if `clone` panics.
391 let mut idx = 0;
392 while let Some(next) = self.first_filled_slot_from(idx) {
393 out.insert_at(next, self.get_unchecked(next).clone());
394 idx = next + 1;
395 }
396 }
397 }
398
399 out
400 }
401}
402
403// This impl is usually not used. `StableVec` has its own impl which doesn't
404// use this one.
405impl<T> fmt::Debug for BitVecCore<T> {
406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407 f.debug_struct("BitVecCore")
408 .field("len", &self.len())
409 .field("cap", &self.cap())
410 .finish()
411 }
412}
413
414// Implement `Send` and `Sync`. These are not automatically implemented as we
415// use raw pointers. But they are safe to implement (given that `T` implements
416// them). We do not have interior mutability, thus we can implement `Sync`. We
417// also do not share any data with other instance of this type, meaning that
418// `Send` can be implemented.
419unsafe impl<T: Send> Send for BitVecCore<T> {}
420unsafe impl<T: Sync> Sync for BitVecCore<T> {}
421
422#[inline(always)]
423fn num_usizes_for(cap: usize) -> usize {
424 // We need ⌈new_cap / BITS_PER_USIZE⌉ many usizes to store all required
425 // bits. We do rounding up by first adding the (BITS_PER_USIZE - 1).
426 (cap + (BITS_PER_USIZE - 1)) / BITS_PER_USIZE
427}
428
429#[cfg(test)]
430mod tests {
431 use super::*;
432
433 #[test]
434 fn num_usizes() {
435 assert_eq!(num_usizes_for(0), 0);
436 assert_eq!(num_usizes_for(1), 1);
437 assert_eq!(num_usizes_for(2), 1);
438 assert_eq!(num_usizes_for(3), 1);
439
440 #[cfg(target_pointer_width = "64")]
441 {
442 assert_eq!(num_usizes_for(63), 1);
443 assert_eq!(num_usizes_for(64), 1);
444 assert_eq!(num_usizes_for(65), 2);
445 assert_eq!(num_usizes_for(66), 2);
446 assert_eq!(num_usizes_for(66), 2);
447
448 assert_eq!(num_usizes_for(255), 4);
449 assert_eq!(num_usizes_for(256), 4);
450 assert_eq!(num_usizes_for(257), 5);
451 assert_eq!(num_usizes_for(258), 5);
452 assert_eq!(num_usizes_for(259), 5);
453 }
454
455 #[cfg(target_pointer_width = "32")]
456 {
457 assert_eq!(num_usizes_for(31), 1);
458 assert_eq!(num_usizes_for(32), 1);
459 assert_eq!(num_usizes_for(33), 2);
460 assert_eq!(num_usizes_for(34), 2);
461 assert_eq!(num_usizes_for(35), 2);
462
463 assert_eq!(num_usizes_for(127), 4);
464 assert_eq!(num_usizes_for(128), 4);
465 assert_eq!(num_usizes_for(129), 5);
466 assert_eq!(num_usizes_for(130), 5);
467 assert_eq!(num_usizes_for(131), 5);
468 }
469 }
470}