diff options
Diffstat (limited to 'src/seg_queue.rs')
-rw-r--r-- | src/seg_queue.rs | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/src/seg_queue.rs b/src/seg_queue.rs index 1767775..2761dc0 100644 --- a/src/seg_queue.rs +++ b/src/seg_queue.rs @@ -35,6 +35,11 @@ struct Slot<T> { } impl<T> Slot<T> { + const UNINIT: Self = Self { + value: UnsafeCell::new(MaybeUninit::uninit()), + state: AtomicUsize::new(0), + }; + /// Waits until a value is written into the slot. fn wait_write(&self) { let backoff = Backoff::new(); @@ -58,13 +63,10 @@ struct Block<T> { impl<T> Block<T> { /// Creates an empty block that starts at `start_index`. fn new() -> Block<T> { - // SAFETY: This is safe because: - // [1] `Block::next` (AtomicPtr) may be safely zero initialized. - // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. - // [3] `Slot::value` (UnsafeCell) may be safely zero initialized because it - // holds a MaybeUninit. - // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + Self { + next: AtomicPtr::new(ptr::null_mut()), + slots: [Slot::UNINIT; BLOCK_CAP], + } } /// Waits until the next pointer is set. @@ -437,9 +439,9 @@ impl<T> SegQueue<T> { impl<T> Drop for SegQueue<T> { fn drop(&mut self) { - let mut head = self.head.index.load(Ordering::Relaxed); - let mut tail = self.tail.index.load(Ordering::Relaxed); - let mut block = self.head.block.load(Ordering::Relaxed); + let mut head = *self.head.index.get_mut(); + let mut tail = *self.tail.index.get_mut(); + let mut block = *self.head.block.get_mut(); // Erase the lower bits. head &= !((1 << SHIFT) - 1); @@ -457,7 +459,7 @@ impl<T> Drop for SegQueue<T> { p.as_mut_ptr().drop_in_place(); } else { // Deallocate the block and move to the next one. - let next = (*block).next.load(Ordering::Relaxed); + let next = *(*block).next.get_mut(); drop(Box::from_raw(block)); block = next; } |