Skip to content

Commit 00be0d8

Browse files
committed
add: extend_from_slice_atomic()
1 parent 58d68a1 commit 00be0d8

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

src/lib.rs

+35
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,41 @@ impl<H, T> HeaderVec<H, T> {
529529
}
530530
}
531531

532+
#[cfg(feature = "atomic_append")]
533+
impl<H, T: Clone> HeaderVec<H, T> {
534+
/// Atomically add items from a slice to the end of the list. without reallocation
535+
///
536+
/// # Errors
537+
///
538+
/// If the vector is full, the item is returned.
539+
///
540+
/// # Safety
541+
///
542+
/// There must be only one thread calling this method at any time. Synchronization has to
543+
/// be provided by the user.
544+
pub unsafe fn extend_from_slice_atomic<'a>(&self, slice: &'a [T]) -> Result<(), &'a [T]> {
545+
#[cfg(debug_assertions)] // only for the race check later
546+
let len = self.len_atomic_relaxed();
547+
if self.spare_capacity() >= slice.len() {
548+
// copy data
549+
let end_ptr = self.end_ptr_atomic_mut();
550+
for (index, item) in slice.iter().enumerate() {
551+
unsafe {
552+
core::ptr::write(end_ptr.add(index), item.clone());
553+
}
554+
}
555+
// correct the len
556+
let len_again = self.len_atomic_add_release(slice.len());
557+
// in debug builds we check for races, the chance to catch these are still pretty minimal
558+
#[cfg(debug_assertions)]
559+
debug_assert_eq!(len_again, len, "len was updated by another thread");
560+
Ok(())
561+
} else {
562+
Err(slice)
563+
}
564+
}
565+
}
566+
532567
impl<H, T> Drop for HeaderVec<H, T> {
533568
fn drop(&mut self) {
534569
unsafe {

tests/atomic_append.rs

+11
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,14 @@ fn test_atomic_append() {
1414
assert_eq!(hv.len(), 3);
1515
assert_eq!(hv.as_slice(), [1, 2, 3]);
1616
}
17+
18+
#[test]
19+
fn test_extend_from_slice() {
20+
let hv = HeaderVec::with_capacity(6, ());
21+
22+
unsafe {
23+
hv.extend_from_slice_atomic(&[0, 1, 2]).unwrap();
24+
hv.extend_from_slice_atomic(&[3, 4, 5]).unwrap();
25+
}
26+
assert_eq!(hv.as_slice(), &[0, 1, 2, 3, 4, 5]);
27+
}

0 commit comments

Comments
 (0)