From 8a5603a2b819c8a9719db4b4ee6c54feef3d3dad Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Sat, 23 Sep 2023 01:37:07 -0700 Subject: [PATCH] fix: reimplement Clone for new LockFreeFrozenVec --- src/sync.rs | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/sync.rs b/src/sync.rs index c2e0a69..73b6f06 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -731,15 +731,42 @@ fn test_non_lockfree_unchecked() { impl Clone for LockFreeFrozenVec { fn clone(&self) -> Self { - let cap = self.cap.load(Ordering::Acquire); let len = self.len.load(Ordering::Acquire); + // handle the empty case + if len == 0 { + return Self::default(); + } - let new_vec = Self::with_capacity(cap); - for i in 0..len { - new_vec.push(self.get(i).unwrap()); + // copy the data + let data = [Self::NULL; NUM_BUFFERS]; + // for each buffer, copy the data + for i in 0..NUM_BUFFERS { + // get the buffer size and index + let buffer_size = buffer_size(i); + let buffer_idx = buffer_index(buffer_size - 1); + // get the buffer pointer + let buffer_ptr = self.data[buffer_idx].load(Ordering::Acquire); + if buffer_ptr.is_null() { + // no data in this buffer + break; + } + // allocate a new buffer + let layout = Self::layout(buffer_size); + let new_buffer_ptr = unsafe { std::alloc::alloc(layout).cast::() }; + assert!(!new_buffer_ptr.is_null()); + // copy the data + unsafe { + std::ptr::copy_nonoverlapping(buffer_ptr, new_buffer_ptr, buffer_size); + } + // store the new buffer pointer + data[i].store(new_buffer_ptr, Ordering::Release); } - new_vec + return Self { + data, + len: AtomicUsize::new(len), + locked: AtomicBool::new(false), + }; } } @@ -774,6 +801,12 @@ fn test_non_lockfree() { } }); + // Test cloning + let vec2 = vec.clone(); + assert_eq!(vec2.get(0), Some(Moo(1))); + assert_eq!(vec2.get(1), Some(Moo(2))); + assert_eq!(vec2.get(2), Some(Moo(3))); + // Test dropping empty vecs LockFreeFrozenVec::<()>::new(); }