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 00be0d8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,41 @@ 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());

Check warning on line 556 in src/lib.rs

View workflow job for this annotation

GitHub Actions / benches

unused variable: `len_again`
// in debug builds we check for races, the chance to catch these are still pretty minimal
#[cfg(debug_assertions)]
debug_assert_eq!(len_again, len, "len was updated by another thread");
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 00be0d8

Please sign in to comment.