From b200e6fc3e591f67646832adb9bbf129ee2b2761 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 3 Dec 2020 23:52:55 +0100 Subject: core: add plumbing for canceling ops when closing a resource (#8661) --- core/async_cell.rs | 74 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 28 deletions(-) (limited to 'core/async_cell.rs') diff --git a/core/async_cell.rs b/core/async_cell.rs index a140dceb1..bf62692ed 100644 --- a/core/async_cell.rs +++ b/core/async_cell.rs @@ -126,6 +126,7 @@ impl RcRef> { /// let foo_rc: RcRef = RcRef::map(stuff_rc.clone(), |v| &v.foo); /// let bar_rc: RcRef = RcRef::map(stuff_rc, |v| &v.bar); /// ``` +#[derive(Debug)] pub struct RcRef { rc: Rc, value: *const T, @@ -136,7 +137,7 @@ impl RcRef { Self::from(Rc::new(value)) } - pub fn map, F: FnOnce(&S) -> &T>( + pub fn map, F: FnOnce(&S) -> &T>( source: R, map_fn: F, ) -> RcRef { @@ -144,6 +145,11 @@ impl RcRef { let value = map_fn(unsafe { &*value }); RcRef { rc, value } } + + pub(crate) fn split(rc_ref: &Self) -> (&T, &Rc) { + let &Self { ref rc, value } = rc_ref; + (unsafe { &*value }, rc) + } } impl Default for RcRef { @@ -152,6 +158,21 @@ impl Default for RcRef { } } +impl Clone for RcRef { + fn clone(&self) -> Self { + Self { + rc: self.rc.clone(), + value: self.value, + } + } +} + +impl From<&RcRef> for RcRef { + fn from(rc_ref: &RcRef) -> Self { + rc_ref.clone() + } +} + impl From> for RcRef { fn from(rc: Rc) -> Self { Self { @@ -161,12 +182,9 @@ impl From> for RcRef { } } -impl Clone for RcRef { - fn clone(&self) -> Self { - Self { - rc: self.rc.clone(), - value: self.value, - } +impl From<&Rc> for RcRef { + fn from(rc: &Rc) -> Self { + rc.clone().into() } } @@ -189,8 +207,18 @@ impl AsRef for RcRef { } } +/// The `RcLike` trait provides an abstraction over `std::rc::Rc` and `RcRef`, +/// so that applicable methods can operate on either type. +pub trait RcLike: AsRef + Into> {} + +impl RcLike for Rc {} +impl RcLike for RcRef {} +impl RcLike for &Rc {} +impl RcLike for &RcRef {} + mod internal { use super::AsyncRefCell; + use super::RcLike; use super::RcRef; use futures::future::Future; use futures::ready; @@ -204,32 +232,29 @@ mod internal { use std::ops::Deref; use std::ops::DerefMut; use std::pin::Pin; - use std::rc::Rc; impl AsyncRefCell { /// Borrow the cell's contents synchronouslym without creating an /// intermediate future. If the cell has already been borrowed and either /// the existing or the requested borrow is exclusive, this function returns - /// `None`. - pub(super) fn borrow_sync< - M: BorrowModeTrait, - R: RcLike>, - >( - cell: &R, + /// `None`. + pub fn borrow_sync>>( + cell: R, ) -> Option> { + let cell_ref = cell.as_ref(); // Don't allow synchronous borrows to cut in line; if there are any // enqueued waiters, return `None`, even if the current borrow is a shared // one and the requested borrow is too. - let waiters = unsafe { &mut *cell.waiters.as_ptr() }; + let waiters = unsafe { &mut *cell_ref.waiters.as_ptr() }; if waiters.is_empty() { // There are no enqueued waiters, but it is still possible that the cell // is currently borrowed. If there are no current borrows, or both the // existing and requested ones are shared, `try_add()` returns the // adjusted borrow count. let new_borrow_count = - cell.borrow_count.get().try_add(M::borrow_mode())?; - cell.borrow_count.set(new_borrow_count); - Some(AsyncBorrowImpl::::new(cell.clone().into())) + cell_ref.borrow_count.get().try_add(M::borrow_mode())?; + cell_ref.borrow_count.set(new_borrow_count); + Some(AsyncBorrowImpl::::new(cell.into())) } else { None } @@ -359,10 +384,10 @@ mod internal { } impl AsyncBorrowFutureImpl { - pub fn new>>(cell: &R) -> Self { + pub fn new>>(cell: R) -> Self { Self { - cell: Some(cell.clone().into()), - id: cell.create_waiter::(), + id: cell.as_ref().create_waiter::(), + cell: Some(cell.into()), _phantom: PhantomData, } } @@ -561,13 +586,6 @@ mod internal { self.waker.take() } } - - /// The `RcLike` trait provides an abstraction over `std::rc::Rc` and `RcRef`, - /// so that applicable methods can operate on either type. - pub trait RcLike: Clone + Deref + Into> {} - - impl RcLike for Rc {} - impl RcLike for RcRef {} } #[cfg(test)] -- cgit v1.2.3