From a8ee1c0fa315d00ee7dbb73e2d6c26556b75c8f1 Mon Sep 17 00:00:00 2001 From: Kaede Hoshikawa Date: Mon, 15 Aug 2022 07:05:41 +0900 Subject: [PATCH] Cell or UnsafeCell? --- packages/yew/src/platform/pinned/mpsc.rs | 44 +++++++++------------ packages/yew/src/platform/pinned/oneshot.rs | 32 +++++---------- 2 files changed, 27 insertions(+), 49 deletions(-) diff --git a/packages/yew/src/platform/pinned/mpsc.rs b/packages/yew/src/platform/pinned/mpsc.rs index 8a481e8ba83..b72a9a26cf1 100644 --- a/packages/yew/src/platform/pinned/mpsc.rs +++ b/packages/yew/src/platform/pinned/mpsc.rs @@ -1,5 +1,6 @@ //! A multi-producer single-receiver channel. +use std::cell::UnsafeCell; use std::collections::VecDeque; use std::marker::PhantomData; use std::rc::Rc; @@ -40,19 +41,6 @@ struct Inner { } impl Inner { - /// Creates a unchecked mutable reference from an immutable reference. - /// - /// SAFETY: You can only use this when: - /// - /// 1. The mutable reference is released at the end of a function call. - /// 2. No parent function has acquired the mutable reference. - /// 3. The caller is not an async function / the mutable reference is released before an await - /// statement. - #[inline] - unsafe fn get_mut_unchecked(&self) -> *mut Self { - self as *const Self as *mut Self - } - fn close(&mut self) { self.closed = true; @@ -65,7 +53,7 @@ impl Inner { /// The receiver of an unbounded mpsc channel. #[derive(Debug)] pub struct UnboundedReceiver { - inner: Rc>, + inner: Rc>>, } impl UnboundedReceiver { @@ -78,7 +66,7 @@ impl UnboundedReceiver { pub fn try_next(&self) -> std::result::Result, TryRecvError> { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; match (inner.items.pop_front(), inner.closed) { (Some(m), _) => Ok(Some(m)), @@ -99,7 +87,7 @@ impl Stream for UnboundedReceiver { ) -> std::task::Poll> { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; match (inner.items.pop_front(), inner.closed) { (Some(m), _) => Poll::Ready(Some(m)), @@ -114,7 +102,10 @@ impl Stream for UnboundedReceiver { impl FusedStream for UnboundedReceiver { fn is_terminated(&self) -> bool { - self.inner.items.is_empty() && self.inner.closed + // SAFETY: This function is not used by any other functions and hence uniquely owns the + // reference. + let inner = unsafe { &*self.inner.get() }; + inner.items.is_empty() && inner.closed } } @@ -122,7 +113,7 @@ impl Drop for UnboundedReceiver { fn drop(&mut self) { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; inner.close(); } } @@ -130,7 +121,7 @@ impl Drop for UnboundedReceiver { /// The sender of an unbounded mpsc channel. #[derive(Debug)] pub struct UnboundedSender { - inner: Rc>, + inner: Rc>>, } impl UnboundedSender { @@ -138,7 +129,7 @@ impl UnboundedSender { pub fn send_now(&self, item: T) -> Result<(), SendError> { // SAFETY: This function is not used by any function that have already acquired a mutable // reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; if inner.closed { return Err(SendError { inner: item }); @@ -157,7 +148,7 @@ impl UnboundedSender { pub fn close_now(&self) { // SAFETY: This function is not used by any other functions that have acquired a mutable // reference and hence uniquely owns the mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; inner.close(); } } @@ -170,7 +161,7 @@ impl Clone for UnboundedSender { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; inner.sender_ctr += 1; self_ @@ -181,7 +172,7 @@ impl Drop for UnboundedSender { fn drop(&mut self) { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; let sender_ctr = { inner.sender_ctr -= 1; @@ -207,7 +198,8 @@ impl Sink for &'_ UnboundedSender { self: std::pin::Pin<&mut Self>, _cx: &mut std::task::Context<'_>, ) -> Poll> { - match self.inner.closed { + let inner = unsafe { &*self.inner.get() }; + match inner.closed { false => Poll::Ready(Ok(())), true => Poll::Ready(Err(TrySendError { _marker: PhantomData, @@ -239,13 +231,13 @@ impl Sink for &'_ UnboundedSender { /// This channel has an infinite buffer and can run out of memory if the channel is not actively /// drained. pub fn unbounded() -> (UnboundedSender, UnboundedReceiver) { - let inner = Rc::new(Inner { + let inner = Rc::new(UnsafeCell::new(Inner { rx_waker: None, closed: false, sender_ctr: 1, items: VecDeque::new(), - }); + })); ( UnboundedSender { diff --git a/packages/yew/src/platform/pinned/oneshot.rs b/packages/yew/src/platform/pinned/oneshot.rs index d0694969ec6..b4eab307068 100644 --- a/packages/yew/src/platform/pinned/oneshot.rs +++ b/packages/yew/src/platform/pinned/oneshot.rs @@ -1,5 +1,6 @@ //! A one-time send - receive channel. +use std::cell::UnsafeCell; use std::future::Future; use std::marker::PhantomData; use std::rc::Rc; @@ -21,25 +22,10 @@ struct Inner { item: Option, } -impl Inner { - /// Creates a unchecked mutable reference from a mutable reference. - /// - /// SAFETY: You can only use this when: - /// - /// 1. The mutable reference is released at the end of a function call. - /// 2. No parent function has acquired the mutable reference. - /// 3. The caller is not an async function / the mutable reference is released before an await - /// statement. - #[inline] - unsafe fn get_mut_unchecked(&self) -> *mut Self { - self as *const Self as *mut Self - } -} - /// The receiver of a oneshot channel. #[derive(Debug)] pub struct Receiver { - inner: Rc>, + inner: Rc>>, } impl Future for Receiver { @@ -48,7 +34,7 @@ impl Future for Receiver { fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; // Implementation Note: // @@ -74,7 +60,7 @@ impl Drop for Receiver { fn drop(&mut self) { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; inner.closed = true; } } @@ -82,7 +68,7 @@ impl Drop for Receiver { /// The sender of a oneshot channel. #[derive(Debug)] pub struct Sender { - inner: Rc>, + inner: Rc>>, } impl Sender { @@ -90,7 +76,7 @@ impl Sender { pub fn send(self, item: T) -> Result<(), T> { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; if inner.closed { return Err(item); @@ -110,7 +96,7 @@ impl Drop for Sender { fn drop(&mut self) { // SAFETY: This function is not used by any other functions and hence uniquely owns the // mutable reference. - let inner = unsafe { &mut *self.inner.get_mut_unchecked() }; + let inner = unsafe { &mut *self.inner.get() }; inner.closed = true; @@ -124,11 +110,11 @@ impl Drop for Sender { /// Creates a oneshot channel. pub fn channel() -> (Sender, Receiver) { - let inner = Rc::new(Inner { + let inner = Rc::new(UnsafeCell::new(Inner { rx_waker: None, closed: false, item: None, - }); + })); ( Sender {