diff --git a/src/lib.rs b/src/lib.rs index 20c5a1b..64384b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,6 +104,23 @@ impl Vec { } } + /// Creates a new `Vec` reusing allocated space from the `self`. + /// + /// # Examples + /// ``` + /// let vec = boxcar::Vec::new(); + /// vec.push(1); + /// vec.push(2); + /// + /// let mut vec = vec; + /// vec.clear(); + /// assert_eq!(vec.count(), 0); + /// vec.push(3); // will not allocate + /// ``` + pub fn clear(&mut self) { + self.raw.clear(); + } + /// Reserves capacity for at least `additional` more elements to be inserted /// in the given `Vec`. The collection may reserve more space to avoid /// frequent reallocations. diff --git a/src/raw.rs b/src/raw.rs index ffd1b1a..441375d 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -56,6 +56,26 @@ impl Vec { } } + pub fn clear(&mut self) { + self.count.store(0, Ordering::Relaxed); + self.inflight.store(0, Ordering::Relaxed); + + for (i, b) in self.buckets.iter_mut().enumerate() { + let e = b.entries.load(Ordering::Relaxed); + if e.is_null() { + continue; + } + + let len = Location::bucket_capacity(i); + for i in 0..len { + let e = unsafe { &mut *e.add(i) }; + if e.active.swap(false, Ordering::Relaxed) { + unsafe { ptr::drop_in_place((*e.slot.get()).as_mut_ptr()) } + } + } + } + } + /// Returns the number of elements in the vector. pub fn count(&self) -> usize { self.count.load(Ordering::Acquire) diff --git a/tests/vec.rs b/tests/vec.rs index 5029fe5..1739c67 100644 --- a/tests/vec.rs +++ b/tests/vec.rs @@ -1,3 +1,4 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; use std::{sync::Barrier, thread}; #[test] @@ -21,6 +22,41 @@ fn simple() { } } +#[test] +fn clear() { + struct T<'a>(&'a AtomicUsize); + impl Drop for T<'_> { + fn drop(&mut self) { + self.0.fetch_add(1, Ordering::Relaxed); + } + } + + let drops = AtomicUsize::new(0); + + let mut vec = boxcar::Vec::new(); + vec.push(T(&drops)); + vec.push(T(&drops)); + + let first_ptr: *const _ = vec.iter().next().unwrap().1 as _; + + vec.clear(); + assert_eq!(vec.count(), 0); + assert_eq!(vec.iter().count(), 0); + assert_eq!(drops.swap(0, Ordering::Relaxed), 2); + + vec.clear(); + assert_eq!(vec.count(), 0); + assert_eq!(vec.iter().count(), 0); + assert_eq!(drops.load(Ordering::Relaxed), 0); + + vec.push(T(&drops)); + let ptr: *const _ = vec.iter().next().unwrap().1 as _; + assert_eq!(ptr, first_ptr); + + drop(vec); + assert_eq!(drops.load(Ordering::Relaxed), 1); +} + #[test] fn stress() { let vec = boxcar::Vec::new();