From e316b3ed37baadf57f9002d69b1baba7d1b1664c Mon Sep 17 00:00:00 2001 From: Caleb Sander Date: Mon, 15 Jan 2024 10:21:43 -0500 Subject: [PATCH] counter: use NonNull counter::{Sender, Receiver} hold shared references to a channel, similar to an Arc. Their raw pointers to the Counter are never null, so change them from *mut Counter to NonNull>. This makes it easier to verify the safety requirements for dereferences, and allows the niche value optimization to apply. --- crossbeam-channel/src/counter.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/crossbeam-channel/src/counter.rs b/crossbeam-channel/src/counter.rs index 48fd113d9..582262964 100644 --- a/crossbeam-channel/src/counter.rs +++ b/crossbeam-channel/src/counter.rs @@ -3,6 +3,7 @@ use std::isize; use std::ops; use std::process; +use std::ptr::NonNull; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; /// Reference counter internals. @@ -22,12 +23,12 @@ struct Counter { /// Wraps a channel into the reference counter. pub(crate) fn new(chan: C) -> (Sender, Receiver) { - let counter = Box::into_raw(Box::new(Counter { + let counter = NonNull::from(Box::leak(Box::new(Counter { senders: AtomicUsize::new(1), receivers: AtomicUsize::new(1), destroy: AtomicBool::new(false), chan, - })); + }))); let s = Sender { counter }; let r = Receiver { counter }; (s, r) @@ -35,13 +36,13 @@ pub(crate) fn new(chan: C) -> (Sender, Receiver) { /// The sending side. pub(crate) struct Sender { - counter: *mut Counter, + counter: NonNull>, } impl Sender { /// Returns the internal `Counter`. fn counter(&self) -> &Counter { - unsafe { &*self.counter } + unsafe { self.counter.as_ref() } } /// Acquires another sender reference. @@ -68,7 +69,7 @@ impl Sender { disconnect(&self.counter().chan); if self.counter().destroy.swap(true, Ordering::AcqRel) { - drop(unsafe { Box::from_raw(self.counter) }); + drop(unsafe { Box::from_raw(self.counter.as_ptr()) }); } } } @@ -90,13 +91,13 @@ impl PartialEq for Sender { /// The receiving side. pub(crate) struct Receiver { - counter: *mut Counter, + counter: NonNull>, } impl Receiver { /// Returns the internal `Counter`. fn counter(&self) -> &Counter { - unsafe { &*self.counter } + unsafe { self.counter.as_ref() } } /// Acquires another receiver reference. @@ -123,7 +124,7 @@ impl Receiver { disconnect(&self.counter().chan); if self.counter().destroy.swap(true, Ordering::AcqRel) { - drop(unsafe { Box::from_raw(self.counter) }); + drop(unsafe { Box::from_raw(self.counter.as_ptr()) }); } } }