From 5b74dc8acca8b915af29d12ae0a43bde15c5df97 Mon Sep 17 00:00:00 2001 From: John Nunley <dev@notgull.net> Date: Thu, 25 Apr 2024 22:53:55 -0700 Subject: [PATCH] Merge fetch_and andthe prev_value check cc https://github.com/smol-rs/concurrent-queue/pull/58#discussion_r1574686897 Signed-off-by: John Nunley <dev@notgull.net> --- src/single.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/single.rs b/src/single.rs index 048f486..f88c478 100644 --- a/src/single.rs +++ b/src/single.rs @@ -65,23 +65,27 @@ impl<T> Single<T> { } if prev == state { - // Swap out the value. - // SAFETY: We have locked the state. - let prev_value = unsafe { - self.slot - .with_mut(move |slot| ptr::replace(slot, MaybeUninit::new(value))) - }; - - // We can unlock the slot now. - self.state.fetch_and(!LOCKED, Ordering::Release); - - // If the value was pushed, initialize it and return it. + // If the value was pushed, swap out the value. let prev_value = if prev & PUSHED == 0 { + // SAFETY: write is safe because we have locked the state. + self.slot.with_mut(|slot| unsafe { + slot.write(MaybeUninit::new(value)); + }); None } else { - Some(unsafe { prev_value.assume_init() }) + // SAFETY: replace is safe because we have locked the state, and + // assume_init is safe because we have checked that the value was pushed. + let prev_value = unsafe { + self.slot.with_mut(move |slot| { + ptr::replace(slot, MaybeUninit::new(value)).assume_init() + }) + }; + Some(prev_value) }; + // We can unlock the slot now. + self.state.fetch_and(!LOCKED, Ordering::Release); + // Return the old value. return Ok(prev_value); }