Skip to content

Commit

Permalink
add: extend_from_slice_atomic()
Browse files Browse the repository at this point in the history
  • Loading branch information
cehteh committed Sep 23, 2024
1 parent 58d68a1 commit 2fae9c2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,40 @@ impl<H, T> HeaderVec<H, T> {
}
}

#[cfg(feature = "atomic_append")]
impl<H, T: Clone> HeaderVec<H, T> {
/// Atomically add items from a slice to the end of the list. without reallocation
///
/// # Errors
///
/// If the vector is full, the item is returned.
///
/// # Safety
///
/// There must be only one thread calling this method at any time. Synchronization has to
/// be provided by the user.
pub unsafe fn extend_from_slice_atomic<'a>(&self, slice: &'a [T]) -> Result<(), &'a [T]> {
#[cfg(debug_assertions)] // only for the race check later
let len = self.len_atomic_relaxed();
if self.spare_capacity() >= slice.len() {
// copy data
let end_ptr = self.end_ptr_atomic_mut();
for (index, item) in slice.iter().enumerate() {
unsafe {
core::ptr::write(end_ptr.add(index), item.clone());
}
}
// correct the len
let len_again = self.len_atomic_add_release(slice.len());
// in debug builds we check for races, the chance to catch these are still pretty minimal
debug_assert_eq!(len_again, len, "len was updated by another thread");

Check failure on line 558 in src/lib.rs

View workflow job for this annotation

GitHub Actions / benches

cannot find value `len` in this scope
Ok(())
} else {
Err(slice)
}
}
}

impl<H, T> Drop for HeaderVec<H, T> {
fn drop(&mut self) {
unsafe {
Expand Down
11 changes: 11 additions & 0 deletions tests/atomic_append.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,14 @@ fn test_atomic_append() {
assert_eq!(hv.len(), 3);
assert_eq!(hv.as_slice(), [1, 2, 3]);
}

#[test]
fn test_extend_from_slice() {
let hv = HeaderVec::with_capacity(6, ());

unsafe {
hv.extend_from_slice_atomic(&[0, 1, 2]).unwrap();
hv.extend_from_slice_atomic(&[3, 4, 5]).unwrap();
}
assert_eq!(hv.as_slice(), &[0, 1, 2, 3, 4, 5]);
}

0 comments on commit 2fae9c2

Please sign in to comment.