diff --git a/wb_async_utils/src/lib.rs b/wb_async_utils/src/lib.rs index 9e1598e..5917851 100644 --- a/wb_async_utils/src/lib.rs +++ b/wb_async_utils/src/lib.rs @@ -15,3 +15,17 @@ pub mod spsc; #[cfg(feature = "ufotofu_utils")] pub mod shared_producer; + +// This is safe if and only if the object pointed at by `reference` lives for at least `'longer`. +// See https://doc.rust-lang.org/nightly/std/intrinsics/fn.transmute.html for more detail. +pub(crate) unsafe fn extend_lifetime<'shorter, 'longer, T: ?Sized>(reference: &'shorter T) -> &'longer T { + core::mem::transmute::<&'shorter T, &'longer T>(reference) +} + +// This is safe if and only if the object pointed at by `reference` lives for at least `'longer`. +// See https://doc.rust-lang.org/nightly/std/intrinsics/fn.transmute.html for more detail. +pub(crate) unsafe fn extend_lifetime_mut<'shorter, 'longer, T: ?Sized>( + reference: &'shorter mut T, +) -> &'longer mut T { + core::mem::transmute::<&'shorter mut T, &'longer mut T>(reference) +} \ No newline at end of file diff --git a/wb_async_utils/src/mutex.rs b/wb_async_utils/src/mutex.rs index 8d52411..938d9d7 100644 --- a/wb_async_utils/src/mutex.rs +++ b/wb_async_utils/src/mutex.rs @@ -1,5 +1,5 @@ use core::{ - cell::{Cell, UnsafeCell}, + cell::Cell, future::Future, ops::{Deref, DerefMut}, pin::Pin, @@ -8,36 +8,83 @@ use core::{ use std::collections::VecDeque; use std::fmt; +use fairly_unsafe_cell::*; + +use crate::{extend_lifetime, extend_lifetime_mut}; + /// An awaitable, single-threaded mutex. Only a single reference to the contents of the mutex can exist at any time. /// /// All accesses are parked and waked in FIFO order. pub struct Mutex { - value: UnsafeCell, + value: FairlyUnsafeCell, currently_used: Cell, - parked: UnsafeCell>, // push_back to enqueue, pop_front to dequeue + parked: FairlyUnsafeCell>, // push_back to enqueue, pop_front to dequeue } impl Mutex { /// Creates a new mutex storing the given value. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// + /// let m = Mutex::new(5); + /// assert_eq!(5, m.into_inner()); + /// ``` pub fn new(value: T) -> Self { Mutex { - value: UnsafeCell::new(value), + value: FairlyUnsafeCell::new(value), currently_used: Cell::new(false), - parked: UnsafeCell::new(VecDeque::new()), + parked: FairlyUnsafeCell::new(VecDeque::new()), } } /// Consumes the mutex and returns the wrapped value. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// + /// let m = Mutex::new(5); + /// assert_eq!(5, m.into_inner()); + /// ``` pub fn into_inner(self) -> T { self.value.into_inner() } /// Gives read access to the wrapped value, waiting if necessary. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// let handle = m.read().await; + /// assert_eq!(0, *handle.deref()); + /// }); + /// ``` pub async fn read(&self) -> ReadGuard { ReadFuture(self).await } /// Gives read access if doing so is possible without waiting, returns `None` otherwise. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let m = Mutex::new(0); + /// assert_eq!(&0, m.try_read().unwrap().deref()); + /// + /// block_on(futures::future::join(async { + /// let handle = m.read().await; + /// Timer::after(Duration::from_millis(50)).await; + /// }, async { + /// assert!(m.try_read().is_none()); + /// })); + /// ``` pub fn try_read(&self) -> Option> { if self.currently_used.get() { return None; @@ -48,11 +95,48 @@ impl Mutex { } /// Gives write access to the wrapped value, waiting if necessary. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::{Deref, DerefMut}; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let m = Mutex::new(0); + /// block_on(futures::future::join(async { + /// let mut handle = m.write().await; + /// // Simulate doing some work. + /// Timer::after(Duration::from_millis(50)).await; + /// assert_eq!(0, *handle.deref()); + /// *handle.deref_mut() = 1; + /// }, async { + /// // This future is "faster", but has to wait for the "work" performed by the first one. + /// let mut handle = m.write().await; + /// assert_eq!(1, *handle.deref()); + /// })); + /// ``` pub async fn write(&self) -> WriteGuard { WriteFuture(self).await } /// Gives write access if doing so is possible without waiting, returns `None` otherwise. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let m = Mutex::new(0); + /// assert_eq!(&0, m.try_write().unwrap().deref()); + /// + /// block_on(futures::future::join(async { + /// let handle = m.write().await; + /// Timer::after(Duration::from_millis(50)).await; + /// }, async { + /// assert!(m.try_write().is_none()); + /// })); + /// ``` pub fn try_write(&self) -> Option> { if self.currently_used.get() { return None; @@ -63,7 +147,18 @@ impl Mutex { } /// Sets the wrapped value. - /// Needs to `.await` read access internally. + /// Needs to `.await` write access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// m.set(1).await; + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn set(&self, to: T) { let mut guard = self.write().await; *guard = to; @@ -71,6 +166,17 @@ impl Mutex { /// Replaces the wrapped value, and returns the old one. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// assert_eq!(0, m.replace(1).await); + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn replace(&self, mut to: T) -> T { let mut guard = self.write().await; core::mem::swap(guard.deref_mut(), &mut to); @@ -79,6 +185,17 @@ impl Mutex { /// Updates the wrapped value with the given function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// m.update(|x| x + 1).await; + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn update(&self, with: impl FnOnce(&T) -> T) { let mut guard = self.write().await; *guard = with(&guard); @@ -86,32 +203,68 @@ impl Mutex { /// Updates the wrapped value with the successful result of the given function, or propagates the error of the function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// assert_eq!(Ok(()), m.fallible_update(|x| Ok::(x + 1)).await); + /// assert_eq!(1, *m.read().await.deref()); + /// + /// assert_eq!(Err(-17), m.fallible_update(|_| Err(-17)).await); + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn fallible_update(&self, with: impl FnOnce(&T) -> Result) -> Result<(), E> { let mut guard = self.write().await; *guard = with(&guard)?; Ok(()) } - /// Updates the wrapped value with the given async function. - /// Needs to `.await` read access internally. - pub async fn update_async>(&self, with: impl FnOnce(&T) -> Fut) { - let mut guard = self.write().await; - *guard = with(&guard).await; - } - - /// Updates the wrapped value with the successful result of the given async function, or propagates the error of the function. - /// Needs to `.await` read access internally. - pub async fn fallible_update_async>>( - &self, - with: impl FnOnce(&T) -> Fut, - ) -> Result<(), E> { - let mut guard = self.write().await; - *guard = with(&guard).await?; - Ok(()) - } + // /// Updates the wrapped value with the given async function. + // /// Needs to `.await` read access internally. + // /// + // /// ``` + // /// use wb_async_utils::mutex::*; + // /// use core::ops::Deref; + // /// + // /// let m = Mutex::new(0); + // /// pollster::block_on(async { + // /// m.update_async(move |x| {async move {x + 1}}).await; + // /// assert_eq!(1, *m.read().await.deref()); + // /// }); + // /// ``` + // pub async fn update_async>(&self, with: impl FnOnce(&T) -> Fut) { + // let mut guard = self.write().await; + // *guard = with(&guard).await; + // } + + // /// Updates the wrapped value with the successful result of the given async function, or propagates the error of the function. + // /// Needs to `.await` read access internally. + // pub async fn fallible_update_async>>( + // &self, + // with: impl FnOnce(&T) -> Fut, + // ) -> Result<(), E> { + // let mut guard = self.write().await; + // *guard = with(&guard).await?; + // Ok(()) + // } /// Mutates the wrapped value with the given function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// m.mutate(|x| *x += 1).await; + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn mutate(&self, with: impl FnOnce(&mut T)) { let mut guard = self.write().await; with(&mut guard) @@ -119,6 +272,23 @@ impl Mutex { /// Mutates the wrapped value with the given fallible function, propagates its error if any. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::mutex::*; + /// use core::ops::Deref; + /// + /// let m = Mutex::new(0); + /// pollster::block_on(async { + /// assert_eq!(Ok(()), m.fallible_mutate(|x| { + /// *x +=1 ; + /// Ok::<(), i8>(()) + /// }).await); + /// assert_eq!(1, *m.read().await.deref()); + /// + /// assert_eq!(Err(-17), m.fallible_mutate(|_| Err(-17)).await); + /// assert_eq!(1, *m.read().await.deref()); + /// }); + /// ``` pub async fn fallible_mutate( &self, with: impl FnOnce(&mut T) -> Result<(), E>, @@ -127,39 +297,43 @@ impl Mutex { with(&mut guard) } - /// Mutates the wrapped value with the given async function. - /// Needs to `.await` read access internally. - pub async fn mutate_async>(&self, with: impl FnOnce(&mut T) -> Fut) { - let mut guard = self.write().await; - with(&mut guard).await - } - - /// Mutates the wrapped value with the given fallible async function, propagates its error if any. - /// Needs to `.await` read access internally. - pub async fn fallible_mutate_async>>( - &self, - with: impl FnOnce(&mut T) -> Fut, - ) -> Result<(), E> { - let mut guard = self.write().await; - with(&mut guard).await - } + // /// Mutates the wrapped value with the given async function. + // /// Needs to `.await` read access internally. + // pub async fn mutate_async>(&self, with: impl FnOnce(&mut T) -> Fut) { + // let mut guard = self.write().await; + // with(&mut guard).await + // } + + // /// Mutates the wrapped value with the given fallible async function, propagates its error if any. + // /// Needs to `.await` read access internally. + // pub async fn fallible_mutate_async>>( + // &self, + // with: impl FnOnce(&mut T) -> Fut, + // ) -> Result<(), E> { + // let mut guard = self.write().await; + // with(&mut guard).await + // } fn wake_next(&self) { - if let Some(waker) = (unsafe { &mut *self.parked.get() }).pop_front() { + // Safe because self.parked is only accessed during `wake_next` and `park_waker` and access does not outlive those functions. + let mut r = unsafe { self.parked.borrow_mut() }; + + if let Some(waker) = r.deref_mut().pop_front() { waker.wake() } } fn park(&self, cx: &mut Context<'_>) { // Safe because self.parked is only accessed during `wake_next` and `park_waker` and access does not outlive those functions. - let parked = unsafe { &mut *self.parked.get() }; - parked.push_back(cx.waker().clone()); + let mut r = unsafe { self.parked.borrow_mut() }; + + r.deref_mut().push_back(cx.waker().clone()); } } impl AsMut for Mutex { fn as_mut(&mut self) -> &mut T { - unsafe { &mut *self.value.get() } // Safe because a `&mut Mutex` can never live at the same time as a `ReadGuard`, `WriteGuard` or another `&mut Mutex` + self.value.get_mut() } } @@ -181,6 +355,18 @@ impl fmt::Debug for Mutex { /// Read-only access to the value stored in a [`Mutex`]. /// /// The wrapped value is accessible via the implementation of `Deref`. +/// +/// ``` +/// use wb_async_utils::mutex::*; +/// use core::ops::Deref; +/// use core::time::Duration; +/// +/// let m = Mutex::new(0); +/// pollster::block_on(async { +/// let handle = m.read().await; +/// assert_eq!(0, *handle.deref()); +/// }); +/// ``` #[derive(Debug)] pub struct ReadGuard<'mutex, T> { mutex: &'mutex Mutex, @@ -197,13 +383,36 @@ impl Deref for ReadGuard<'_, T> { type Target = T; fn deref(&self) -> &T { - unsafe { &*self.mutex.value.get() } // Safe because a ReadGuard can never live at the same time as a WriteGuard or a `&mut Mutex` + let borrowed = unsafe { self.mutex.value.borrow() }; // Safe because a ReadGuard can never live at the same time as another guard or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime(borrowed.deref()) } } } /// Read and write access access to the value stored in a [`Mutex`]. /// /// The wrapped value is accessible via the implementation of `Deref` and `DerefMut`. +/// +/// ``` +/// use wb_async_utils::mutex::*; +/// use core::ops::{Deref, DerefMut}; +/// use core::time::Duration; +/// use smol::{block_on, Timer}; +/// +/// let m = Mutex::new(0); +/// block_on(futures::future::join(async { +/// let mut handle = m.write().await; +/// // Simulate doing some work. +/// Timer::after(Duration::from_millis(50)).await; +/// assert_eq!(0, *handle.deref()); +/// *handle.deref_mut() = 1; +/// }, async { +/// // This future is "faster", but has to wait for the "work" performed by the first one. +/// let mut handle = m.read().await; +/// assert_eq!(1, *handle.deref()); +/// })); +/// ``` #[derive(Debug)] pub struct WriteGuard<'mutex, T> { mutex: &'mutex Mutex, @@ -220,13 +429,19 @@ impl Deref for WriteGuard<'_, T> { type Target = T; fn deref(&self) -> &T { - unsafe { &*self.mutex.value.get() } // Safe because a `&WriteGuard` can never live at the same time as a `&mut WriteGuard` or a `&mut Mutex` + let borrowed = unsafe { self.mutex.value.borrow() }; // Safe because a WriteGuard can never live at the same time as another guard or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime(borrowed.deref()) } } } impl DerefMut for WriteGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.mutex.value.get() } // Safe because a `&mut WriteGuard` can never live at the same time as another `&mut WriteGuard` or a `&mut Mutex` + let mut borrowed = unsafe { self.mutex.value.borrow_mut() }; // Safe because a WriteGuard can never live at the same time as another or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime_mut(borrowed.deref_mut()) } } } diff --git a/wb_async_utils/src/once_cell.rs b/wb_async_utils/src/once_cell.rs index e9d9e5c..fbb3d8a 100644 --- a/wb_async_utils/src/once_cell.rs +++ b/wb_async_utils/src/once_cell.rs @@ -1,17 +1,23 @@ use core::{ - cell::UnsafeCell, future::Future, pin::Pin, task::{Context, Poll, Waker}, }; -use std::collections::VecDeque; use std::fmt; +use std::{ + collections::VecDeque, + ops::{Deref, DerefMut}, +}; + +use fairly_unsafe_cell::FairlyUnsafeCell; + +use crate::extend_lifetime; /// An optional value that can be set to a `Some` at most once, and which allows to `.await` that time. /// /// All accesses before setting the value are parked and waked in FIFO order. pub struct OnceCell { - state: UnsafeCell>, // No references to this escape the lifeitme of a method, and each method creates at most one reference. + state: FairlyUnsafeCell>, // No references to this escape the lifeitme of a method, and each method creates at most one reference. } enum State { @@ -27,20 +33,41 @@ impl Default for OnceCell { impl OnceCell { /// Creates a new, empty [`OnceCell`]. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let c = OnceCell::<()>::new(); + /// assert_eq!(None, c.into_inner()); + /// ``` pub fn new() -> Self { OnceCell { - state: UnsafeCell::new(State::Empty(VecDeque::new())), + state: FairlyUnsafeCell::new(State::Empty(VecDeque::new())), } } /// Creates a new [`OnceCell`] that contains a value. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let c = OnceCell::new_with(17); + /// assert_eq!(Some(17), c.into_inner()); + /// ``` pub fn new_with(t: T) -> Self { OnceCell { - state: UnsafeCell::new(State::Set(t)), + state: FairlyUnsafeCell::new(State::Set(t)), } } /// Consumes the [`OnceCell`] and returns the wrapped value, if there is any. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let c = OnceCell::new_with(17); + /// assert_eq!(Some(17), c.into_inner()); + /// ``` pub fn into_inner(self) -> Option { match self.state.into_inner() { State::Empty(_) => None, @@ -48,30 +75,101 @@ impl OnceCell { } } + /// Returns whether the [`OnceCell`] is currently empty. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let c1 = OnceCell::<()>::new(); + /// assert!(c1.is_empty()); + /// + /// let c2 = OnceCell::new_with(17); + /// assert!(!c2.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + match unsafe { self.state.borrow().deref() } { + State::Empty(_) => true, + State::Set(_) => false, + } + } + /// Obtain a mutable reference to the stored value, or `None` if nothing is stored. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let mut c1 = OnceCell::<()>::new(); + /// assert_eq!(None, c1.try_get_mut()); + /// + /// let mut c2 = OnceCell::new_with(17); + /// assert_eq!(Some(&mut 17), c2.try_get_mut()); + /// ``` pub fn try_get_mut(&mut self) -> Option<&mut T> { - match unsafe { &mut *self.state.get() } { + match self.state.get_mut() { State::Empty(_) => None, State::Set(ref mut t) => Some(t), } } /// Try to obtain an immutable reference to the stored value, or `None` if nothing is stored. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let c1 = OnceCell::<()>::new(); + /// assert_eq!(None, c1.try_get()); + /// + /// let c2 = OnceCell::new_with(17); + /// assert_eq!(Some(&17), c2.try_get()); + /// ``` pub fn try_get(&self) -> Option<&T> { - match unsafe { &*self.state.get() } { + match unsafe { self.state.borrow().deref() } { State::Empty(_) => None, - State::Set(ref t) => Some(t), + State::Set(ref t) => Some(unsafe { + // As long as `&self` is alive, it is impossible to get mutable access to the stored value, + // since `try_get_mut` needs a mutable reference to the cell. + extend_lifetime(t) + }), } } /// Obtain an immutable reference to the stored value, `.await`ing it to be set if necessary. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let cell = OnceCell::new(); + /// + /// pollster::block_on(async { + /// futures::join!(async { + /// assert_eq!(&5, cell.get().await); + /// }, async { + /// assert_eq!(Ok(()), cell.set(5)); + /// }); + /// }); + /// ``` pub async fn get(&self) -> &T { GetFuture(self).await } /// Set the value in the cell if it was empty before, return an error and do nothing if is was not empty. + /// + /// ``` + /// use wb_async_utils::OnceCell; + /// + /// let cell = OnceCell::new(); + /// + /// pollster::block_on(async { + /// futures::join!(async { + /// assert_eq!(&5, cell.get().await); + /// assert_eq!(Err(17), cell.set(17)); + /// }, async { + /// assert_eq!(Ok(()), cell.set(5)); + /// }); + /// }); + /// ``` pub fn set(&self, t: T) -> Result<(), T> { - match unsafe { &mut *self.state.get() } { + match unsafe { self.state.borrow_mut().deref_mut() } { State::Empty(queue) => { for waker in queue.iter() { waker.wake_by_ref(); @@ -81,7 +179,7 @@ impl OnceCell { } unsafe { - *self.state.get() = State::Set(t); + *self.state.borrow_mut().deref_mut() = State::Set(t); } Ok(()) @@ -109,12 +207,16 @@ impl<'cell, T> Future for GetFuture<'cell, T> { type Output = &'cell T; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match unsafe { &mut *self.0.state.get() } { + match unsafe { &mut self.0.state.borrow_mut().deref_mut() } { State::Empty(queue) => { queue.push_back(cx.waker().clone()); Poll::Pending } - State::Set(ref t) => Poll::Ready(t), + State::Set(ref t) => Poll::Ready(unsafe { + // As long as the reference to the cell is alive, it is impossible to get mutable access to the stored value, + // since `try_get_mut` needs a mutable reference to the cell. + extend_lifetime(t) + }), } } } diff --git a/wb_async_utils/src/rw.rs b/wb_async_utils/src/rw.rs index d98e859..01974ea 100644 --- a/wb_async_utils/src/rw.rs +++ b/wb_async_utils/src/rw.rs @@ -1,5 +1,5 @@ use core::{ - cell::{Cell, UnsafeCell}, + cell::Cell, future::Future, hint::unreachable_unchecked, ops::{Deref, DerefMut}, @@ -9,40 +9,87 @@ use core::{ use std::collections::VecDeque; use std::fmt; +use fairly_unsafe_cell::FairlyUnsafeCell; + +use crate::{extend_lifetime, extend_lifetime_mut}; + /// An awaitable, single-threaded read-write lock. Allows an arbitrary number of concurrent immutable accesses, or a single mutable access. /// /// Write accesses are parked and waked in FIFO order, but read accesses always have priority. /// That is, after a write access has completed, all read accesses are granted. /// Only if there are no pending read accesses is the next (in FIFO order) write access granted. pub struct RwLock { - value: UnsafeCell, + value: FairlyUnsafeCell, readers: Cell>, // `None` while writing, `Some(0)` if there are neither readers nor writers - parked_reads: UnsafeCell>, // push_back to enqueue, pop_front to dequeue - parked_writes: UnsafeCell>, // push_back to enqueue, pop_front to dequeue + parked_reads: FairlyUnsafeCell>, // push_back to enqueue, pop_front to dequeue + parked_writes: FairlyUnsafeCell>, // push_back to enqueue, pop_front to dequeue } impl RwLock { /// Creates a new RwLock storing the given value. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// + /// let rw = RwLock::new(5); + /// assert_eq!(5, rw.into_inner()); + /// ``` pub fn new(value: T) -> Self { RwLock { - value: UnsafeCell::new(value), + value: FairlyUnsafeCell::new(value), readers: Cell::new(Some(0)), - parked_reads: UnsafeCell::new(VecDeque::new()), - parked_writes: UnsafeCell::new(VecDeque::new()), + parked_reads: FairlyUnsafeCell::new(VecDeque::new()), + parked_writes: FairlyUnsafeCell::new(VecDeque::new()), } } /// Consumes the RwLock and returns the wrapped value. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// + /// let rw = RwLock::new(5); + /// assert_eq!(5, rw.into_inner()); + /// ``` pub fn into_inner(self) -> T { self.value.into_inner() } /// Gives read access to the wrapped value, waiting if necessary. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// let handle = rw.read().await; + /// assert_eq!(0, *handle.deref()); + /// }); + /// ``` pub async fn read(&self) -> ReadGuard { ReadFuture(self).await } /// Gives read access if doing so is possible without waiting, returns `None` otherwise. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let rw = RwLock::new(0); + /// assert_eq!(&0, rw.try_read().unwrap().deref()); + /// + /// block_on(futures::future::join(async { + /// let handle = rw.write().await; + /// Timer::after(Duration::from_millis(50)).await; + /// }, async { + /// assert!(rw.try_read().is_none()); + /// })); + /// ``` pub fn try_read(&self) -> Option> { let reader_count = self.readers.get()?; self.readers.set(Some(reader_count + 1)); @@ -51,11 +98,48 @@ impl RwLock { } /// Gives write access to the wrapped value, waiting if necessary. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::{Deref, DerefMut}; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let rw = RwLock::new(0); + /// block_on(futures::future::join(async { + /// let mut handle = rw.write().await; + /// // Simulate doing some work. + /// Timer::after(Duration::from_millis(50)).await; + /// assert_eq!(0, *handle.deref()); + /// *handle.deref_mut() = 1; + /// }, async { + /// // This future is "faster", but has to wait for the "work" performed by the first one. + /// let mut handle = rw.write().await; + /// assert_eq!(1, *handle.deref()); + /// })); + /// ``` pub async fn write(&self) -> WriteGuard { WriteFuture(self).await } /// Gives write access if doing so is possible without waiting, returns `None` otherwise. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// use core::time::Duration; + /// use smol::{block_on, Timer}; + /// + /// let rw = RwLock::new(0); + /// assert_eq!(&0, rw.try_write().unwrap().deref()); + /// + /// block_on(futures::future::join(async { + /// let handle = rw.write().await; + /// Timer::after(Duration::from_millis(50)).await; + /// }, async { + /// assert!(rw.try_write().is_none()); + /// })); + /// ``` pub fn try_write(&self) -> Option> { match self.readers.get() { Some(0) => { @@ -68,6 +152,17 @@ impl RwLock { /// Sets the wrapped value. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// rw.set(1).await; + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn set(&self, to: T) { let mut guard = self.write().await; *guard = to; @@ -75,6 +170,17 @@ impl RwLock { /// Replaces the wrapped value, and returns the old one. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// assert_eq!(0, rw.replace(1).await); + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn replace(&self, mut to: T) -> T { let mut guard = self.write().await; core::mem::swap(guard.deref_mut(), &mut to); @@ -83,6 +189,17 @@ impl RwLock { /// Updates the wrapped value with the given function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// rw.update(|x| x + 1).await; + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn update(&self, with: impl FnOnce(&T) -> T) { let mut guard = self.write().await; *guard = with(&guard); @@ -90,32 +207,57 @@ impl RwLock { /// Updates the wrapped value with the successful result of the given function, or propagates the error of the function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// assert_eq!(Ok(()), rw.fallible_update(|x| Ok::(x + 1)).await); + /// assert_eq!(1, *rw.read().await.deref()); + /// + /// assert_eq!(Err(-17), rw.fallible_update(|_| Err(-17)).await); + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn fallible_update(&self, with: impl FnOnce(&T) -> Result) -> Result<(), E> { let mut guard = self.write().await; *guard = with(&guard)?; Ok(()) } - /// Updates the wrapped value with the given async function. - /// Needs to `.await` read access internally. - pub async fn update_async>(&self, with: impl FnOnce(&T) -> Fut) { - let mut guard = self.write().await; - *guard = with(&guard).await; - } - - /// Updates the wrapped value with the successful result of the given async function, or propagates the error of the function. - /// Needs to `.await` read access internally. - pub async fn fallible_update_async>>( - &self, - with: impl FnOnce(&T) -> Fut, - ) -> Result<(), E> { - let mut guard = self.write().await; - *guard = with(&guard).await?; - Ok(()) - } + // /// Updates the wrapped value with the given async function. + // /// Needs to `.await` read access internally. + // pub async fn update_async>(&self, with: impl FnOnce(&T) -> Fut) { + // let mut guard = self.write().await; + // *guard = with(&guard).await; + // } + + // /// Updates the wrapped value with the successful result of the given async function, or propagates the error of the function. + // /// Needs to `.await` read access internally. + // pub async fn fallible_update_async>>( + // &self, + // with: impl FnOnce(&T) -> Fut, + // ) -> Result<(), E> { + // let mut guard = self.write().await; + // *guard = with(&guard).await?; + // Ok(()) + // } /// Mutates the wrapped value with the given function. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// rw.mutate(|x| *x += 1).await; + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn mutate(&self, with: impl FnOnce(&mut T)) { let mut guard = self.write().await; with(&mut guard) @@ -123,6 +265,23 @@ impl RwLock { /// Mutates the wrapped value with the given fallible function, propagates its error if any. /// Needs to `.await` read access internally. + /// + /// ``` + /// use wb_async_utils::rw::*; + /// use core::ops::Deref; + /// + /// let rw = RwLock::new(0); + /// pollster::block_on(async { + /// assert_eq!(Ok(()), rw.fallible_mutate(|x| { + /// *x +=1 ; + /// Ok::<(), i8>(()) + /// }).await); + /// assert_eq!(1, *rw.read().await.deref()); + /// + /// assert_eq!(Err(-17), rw.fallible_mutate(|_| Err(-17)).await); + /// assert_eq!(1, *rw.read().await.deref()); + /// }); + /// ``` pub async fn fallible_mutate( &self, with: impl FnOnce(&mut T) -> Result<(), E>, @@ -131,34 +290,36 @@ impl RwLock { with(&mut guard) } - /// Mutates the wrapped value with the given async function. - /// Needs to `.await` read access internally. - pub async fn mutate_async>(&self, with: impl FnOnce(&mut T) -> Fut) { - let mut guard = self.write().await; - with(&mut guard).await - } - - /// Mutates the wrapped value with the given fallible async function, propagates its error if any. - /// Needs to `.await` read access internally. - pub async fn fallible_mutate_async>>( - &self, - with: impl FnOnce(&mut T) -> Fut, - ) -> Result<(), E> { - let mut guard = self.write().await; - with(&mut guard).await - } + // /// Mutates the wrapped value with the given async function. + // /// Needs to `.await` read access internally. + // pub async fn mutate_async>(&self, with: impl FnOnce(&mut T) -> Fut) { + // let mut guard = self.write().await; + // with(&mut guard).await + // } + + // /// Mutates the wrapped value with the given fallible async function, propagates its error if any. + // /// Needs to `.await` read access internally. + // pub async fn fallible_mutate_async>>( + // &self, + // with: impl FnOnce(&mut T) -> Fut, + // ) -> Result<(), E> { + // let mut guard = self.write().await; + // with(&mut guard).await + // } fn wake_next(&self) { debug_assert_eq!(self.readers.get(), Some(0)); - let there_are_no_pending_reads = { (unsafe { &*self.parked_reads.get() }).is_empty() }; + let there_are_no_pending_reads = unsafe { self.parked_reads.borrow().deref().is_empty() }; if there_are_no_pending_reads { - if let Some(next_write) = (unsafe { &mut *self.parked_writes.get() }).pop_front() { + if let Some(next_write) = + unsafe { self.parked_writes.borrow_mut().deref_mut().pop_front() } + { next_write.wake(); } } else { - for parked_read in (unsafe { &mut *self.parked_reads.get() }).drain(..) { + for parked_read in unsafe { self.parked_reads.borrow_mut().deref_mut().drain(..) } { parked_read.wake(); } } @@ -166,20 +327,20 @@ impl RwLock { fn park_read(&self, cx: &mut Context<'_>) { // Safe because self.parked_reads is only accessed during `wake_next` and `park_waker` and access does not outlive those functions. - let parked_reads = unsafe { &mut *self.parked_reads.get() }; - parked_reads.push_back(cx.waker().clone()); + let mut parked_reads = unsafe { self.parked_reads.borrow_mut() }; + parked_reads.deref_mut().push_back(cx.waker().clone()); } fn park_write(&self, cx: &mut Context<'_>) { // Safe because self.parked_reads is only accessed during `wake_next` and `park_waker` and access does not outlive those functions. - let parked_writes = unsafe { &mut *self.parked_writes.get() }; - parked_writes.push_back(cx.waker().clone()); + let mut parked_writes = unsafe { self.parked_writes.borrow_mut() }; + parked_writes.deref_mut().push_back(cx.waker().clone()); } } impl AsMut for RwLock { fn as_mut(&mut self) -> &mut T { - unsafe { &mut *self.value.get() } // Safe because a `&mut RwLock` can never live at the same time as a `ReadGuard`, `WriteGuard` or another `&mut RwLock` + self.value.get_mut() } } @@ -201,6 +362,19 @@ impl fmt::Debug for RwLock { /// Read-only access to the value stored in a [`RwLock`]. /// /// The wrapped value is accessible via the implementation of `Deref`. +/// +/// ``` +/// use wb_async_utils::rw::*; +/// use core::ops::Deref; +/// use core::time::Duration; +/// +/// let rw = RwLock::new(0); +/// pollster::block_on(async { +/// let handle = rw.read().await; +/// assert_eq!(0, *handle.deref()); +/// }); +/// ``` +#[derive(Debug)] pub struct ReadGuard<'lock, T> { lock: &'lock RwLock, } @@ -223,13 +397,37 @@ impl Deref for ReadGuard<'_, T> { type Target = T; fn deref(&self) -> &T { - unsafe { &*self.lock.value.get() } // Safe because a ReadGuard can never live at the same time as a WriteGuard or a `&mut RwLock` + let borrowed = unsafe { self.lock.value.borrow() }; // Safe because a ReadGuard can never live at the same time as a WriteGuard or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime(borrowed.deref()) } } } /// Read and write access access to the value stored in a [`RwLock`]. /// /// The wrapped value is accessible via the implementation of `Deref` and `DerefMut`. +/// +/// ``` +/// use wb_async_utils::rw::*; +/// use core::ops::{Deref, DerefMut}; +/// use core::time::Duration; +/// use smol::{block_on, Timer}; +/// +/// let rw = RwLock::new(0); +/// block_on(futures::future::join(async { +/// let mut handle = rw.write().await; +/// // Simulate doing some work. +/// Timer::after(Duration::from_millis(50)).await; +/// assert_eq!(0, *handle.deref()); +/// *handle.deref_mut() = 1; +/// }, async { +/// // This future is "faster", but has to wait for the "work" performed by the first one. +/// let mut handle = rw.read().await; +/// assert_eq!(1, *handle.deref()); +/// })); +/// ``` +#[derive(Debug)] pub struct WriteGuard<'lock, T> { lock: &'lock RwLock, } @@ -246,13 +444,19 @@ impl Deref for WriteGuard<'_, T> { type Target = T; fn deref(&self) -> &T { - unsafe { &*self.lock.value.get() } // Safe because a `&WriteGuard` can never live at the same time as a `&mut WriteGuard` or a `&mut RwLock` + let borrowed = unsafe { self.lock.value.borrow() }; // Safe because a WriteGuard can never live at the same time as another guard or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime(borrowed.deref()) } } } impl DerefMut for WriteGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.lock.value.get() } // Safe because a `&mut WriteGuard` can never live at the same time as another `&mut WriteGuard` or a `&mut RwLock` + let mut borrowed = unsafe { self.lock.value.borrow_mut() }; // Safe because a WriteGuard can never live at the same time as another guard or a `&mut Mutex`. + // We can only obtain references with a lifetime tied to `borrowed`, but we know the refs to be both alive and exclusive for as long + // as `self`. + unsafe { extend_lifetime_mut(borrowed.deref_mut()) } } } diff --git a/wb_async_utils/src/spsc.rs b/wb_async_utils/src/spsc.rs index b8e156e..424633b 100644 --- a/wb_async_utils/src/spsc.rs +++ b/wb_async_utils/src/spsc.rs @@ -22,7 +22,7 @@ use std::{ use ufotofu::{BufferedConsumer, BufferedProducer, BulkConsumer, BulkProducer, Consumer, Producer}; use ufotofu_queues::Queue; -use crate::{Mutex, TakeCell}; +use crate::{extend_lifetime, extend_lifetime_mut, Mutex, TakeCell}; /// The state shared between the [`Sender`] and the [`Receiver`]. This is fully opaque, but we expose it to give control over where it is allocated. #[derive(Debug)] @@ -398,20 +398,6 @@ impl>, Q: Queue, F, E> BulkProducer for Receive } } -// This is safe if and only if the object pointed at by `reference` lives for at least `'longer`. -// See https://doc.rust-lang.org/nightly/std/intrinsics/fn.transmute.html for more detail. -unsafe fn extend_lifetime<'shorter, 'longer, T: ?Sized>(reference: &'shorter T) -> &'longer T { - std::mem::transmute::<&'shorter T, &'longer T>(reference) -} - -// This is safe if and only if the object pointed at by `reference` lives for at least `'longer`. -// See https://doc.rust-lang.org/nightly/std/intrinsics/fn.transmute.html for more detail. -unsafe fn extend_lifetime_mut<'shorter, 'longer, T: ?Sized>( - reference: &'shorter mut T, -) -> &'longer mut T { - std::mem::transmute::<&'shorter mut T, &'longer mut T>(reference) -} - #[cfg(test)] mod tests { use super::*; diff --git a/wb_async_utils/src/take_cell.rs b/wb_async_utils/src/take_cell.rs index b1b78ef..8637c79 100644 --- a/wb_async_utils/src/take_cell.rs +++ b/wb_async_utils/src/take_cell.rs @@ -1,18 +1,19 @@ use core::{ - cell::UnsafeCell, future::Future, pin::Pin, task::{Context, Poll, Waker}, }; -use std::collections::VecDeque; +use std::{collections::VecDeque, ops::{Deref, DerefMut}}; use std::fmt; +use fairly_unsafe_cell::FairlyUnsafeCell; + /// An async cell akin to an [`Option`], whose value can only be accessed via an async `take` method that non-blocks while the cell is empty. /// /// All accesses are parked and waked in FIFO order. pub struct TakeCell { - value: UnsafeCell>, - parked: UnsafeCell>, // push_back to enqueue, pop_front to dequeue + value: FairlyUnsafeCell>, + parked: FairlyUnsafeCell>, // push_back to enqueue, pop_front to dequeue } impl Default for TakeCell { @@ -23,34 +24,61 @@ impl Default for TakeCell { impl TakeCell { /// Creates a new, empty [`TakeCell`]. + /// + /// ``` + /// use wb_async_utils::TakeCell; + /// + /// let c = TakeCell::<()>::new(); + /// assert_eq!(None, c.into_inner()); + /// ``` pub fn new() -> Self { TakeCell { - value: UnsafeCell::new(None), - parked: UnsafeCell::new(VecDeque::new()), + value: FairlyUnsafeCell::new(None), + parked: FairlyUnsafeCell::new(VecDeque::new()), } } /// Creates a new [`TakeCell`] storing the given value. + /// + /// ``` + /// use wb_async_utils::TakeCell; + /// + /// let c = TakeCell::new_with(17); + /// assert_eq!(Some(17), c.into_inner()); + /// ``` pub fn new_with(value: T) -> Self { TakeCell { - value: UnsafeCell::new(Some(value)), - parked: UnsafeCell::new(VecDeque::new()), + value: FairlyUnsafeCell::new(Some(value)), + parked: FairlyUnsafeCell::new(VecDeque::new()), } } /// Consumes the [`TakeCell`] and returns the wrapped value, if any. + /// + /// ``` + /// use wb_async_utils::TakeCell; + /// + /// let c = TakeCell::new_with(17); + /// assert_eq!(Some(17), c.into_inner()); + /// ``` pub fn into_inner(self) -> Option { self.value.into_inner() } /// Returns whether the [`TakeCell`] is currently empty. + /// + /// ``` + /// use wb_async_utils::TakeCell; + /// + /// let c1 = TakeCell::<()>::new(); + /// assert!(c1.is_empty()); + /// + /// let c2 = TakeCell::new_with(17); + /// assert!(!c2.is_empty()); + /// ``` pub fn is_empty(&self) -> bool { - unsafe { &*self.value.get() }.is_none() - } - - /// Returns how many tasks are currently waiting for the cell to be filled. - pub fn count_waiting(&self) -> usize { - unsafe { &*self.parked.get() }.len() + let r = unsafe { self.value.borrow() }; + r.deref().is_none() } /// Sets the value in the cell. If the cell was empty, wakes up the oldest pending async method call that was waiting for a value in the cell. @@ -62,14 +90,11 @@ impl TakeCell { /// let cell = TakeCell::new(); /// /// pollster::block_on(async { - /// let waitForSetting = async { + /// join!(async { /// assert_eq!(5, cell.take().await); - /// }; - /// let setToFive = async { + /// }, async { /// cell.set(5); - /// }; - /// - /// join!(waitForSetting, setToFive); + /// }); /// }); /// ``` pub fn set(&self, value: T) { @@ -77,29 +102,56 @@ impl TakeCell { } /// Sets the value in the cell, and returns the old value (if any). If the cell was empty, wakes the oldest pending async method call that was waiting for a value in the cell. + /// + /// ``` + /// use futures::join; + /// use wb_async_utils::TakeCell; + /// + /// let cell = TakeCell::new(); + /// + /// pollster::block_on(async { + /// join!(async { + /// assert_eq!(5, cell.take().await) + /// }, async { + /// assert_eq!(None, cell.replace(5)); + /// }); + /// }); + /// ``` pub fn replace(&self, value: T) -> Option { - match unsafe { &mut *self.value.get() }.take() { + let mut r = unsafe { self.value.borrow_mut() }; + + match r.deref_mut().take() { None => { - *unsafe { &mut *self.value.get() } = Some(value); + *r.deref_mut() = Some(value); self.wake_next(); None } Some(old) => { - *unsafe { &mut *self.value.get() } = Some(value); + *r.deref_mut() = Some(value); Some(old) } } } /// Takes the current value out of the cell if there is one, or returns `None` otherwise. + /// + /// ``` + /// use wb_async_utils::TakeCell; + /// + /// let c1 = TakeCell::<()>::new(); + /// assert_eq!(None, c1.try_take()); + /// + /// let c2 = TakeCell::new_with(17); + /// assert_eq!(Some(17), c2.try_take()); + /// ``` pub fn try_take(&self) -> Option { - unsafe { &mut *self.value.get() }.take() + let mut r = unsafe { self.value.borrow_mut() }; + r.deref_mut().take() } /// Takes the current value out of the cell if there is one, waiting for one to arrive if necessary. /// /// ``` - /// use futures::join; /// use wb_async_utils::TakeCell; /// /// let cell = TakeCell::new_with(5); @@ -115,13 +167,49 @@ impl TakeCell { /// Set the value based on the current value (or abscence thereof). /// /// If the cell was empty, this wakes the oldest pending async method call that was waiting for a value in the cell. + /// + /// ``` + /// use futures::join; + /// use wb_async_utils::TakeCell; + /// + /// let cell = TakeCell::new(); + /// + /// pollster::block_on(async { + /// join!(async { + /// assert_eq!(5, cell.take().await); + /// }, async { + /// cell.update(|x| match x { + /// None => 5, + /// Some(_) => 6, + /// }); + /// }); + /// }); + /// ``` pub fn update(&self, with: impl FnOnce(Option) -> T) { self.set(with(self.try_take())) } - /// Fallibly set the value based on the current value (or abscence thereof). If `with` returns an `Err`, the cell is emptied. + /// Fallibly set the value based on the current value (or absence thereof). If `with` returns an `Err`, the cell is emptied. /// /// If the cell was empty and `with` returned `Ok`, this wakes the oldest pending async method call that was waiting for a value in the cell. + /// + /// ``` + /// use futures::join; + /// use wb_async_utils::TakeCell; + /// + /// let cell = TakeCell::new(); + /// + /// pollster::block_on(async { + /// join!(async { + /// assert_eq!(5, cell.take().await); + /// }, async { + /// assert_eq!(Ok(()), cell.fallible_update(|x| match x { + /// None => Ok(5), + /// Some(_) => Err(()), + /// })); + /// }); + /// }); + /// ``` pub fn fallible_update( &self, with: impl FnOnce(Option) -> Result, @@ -129,23 +217,50 @@ impl TakeCell { self.set(with(self.try_take())?); Ok(()) } + + /// Returns how many tasks are currently waiting for the cell to be filled. + /// + /// ``` + /// use futures::join; + /// use wb_async_utils::TakeCell; + /// + /// let cell = TakeCell::new(); + /// + /// pollster::block_on(async { + /// join!(async { + /// assert_eq!(0, cell.count_waiting()); + /// cell.take().await; + /// assert_eq!(0, cell.count_waiting()); + /// }, async { + /// assert_eq!(1, cell.count_waiting()); + /// cell.set(5); + /// }); + /// }); + /// ``` + pub fn count_waiting(&self) -> usize { + let parked = unsafe { self.parked.borrow() }; + parked.deref().len() + } fn wake_next(&self) { - if let Some(waker) = (unsafe { &mut *self.parked.get() }).pop_front() { + let mut parked = unsafe { self.parked.borrow_mut() }; + + if let Some(waker) = parked.deref_mut().pop_front() { waker.wake() } } fn park(&self, cx: &mut Context<'_>) { - let parked = unsafe { &mut *self.parked.get() }; - parked.push_back(cx.waker().clone()); + let mut parked = unsafe { self.parked.borrow_mut() }; + + parked.deref_mut().push_back(cx.waker().clone()); } } impl fmt::Debug for TakeCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_tuple("TakeCell"); - match unsafe { &*self.value.get() } { + match unsafe { self.value.borrow().deref() } { Some(t) => { d.field(t); }