summaryrefslogtreecommitdiff
path: root/core/async_cell.rs
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2020-12-03 23:52:55 +0100
committerBert Belder <bertbelder@gmail.com>2020-12-09 15:58:36 +0100
commitb200e6fc3e591f67646832adb9bbf129ee2b2761 (patch)
treeb04c877ee5c66ebcf3b611b2ca5c743d0c7374ec /core/async_cell.rs
parentb1379b7de3045000c1f4fd76a503b4e639946348 (diff)
core: add plumbing for canceling ops when closing a resource (#8661)
Diffstat (limited to 'core/async_cell.rs')
-rw-r--r--core/async_cell.rs74
1 files changed, 46 insertions, 28 deletions
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<T> RcRef<AsyncRefCell<T>> {
/// let foo_rc: RcRef<u32> = RcRef::map(stuff_rc.clone(), |v| &v.foo);
/// let bar_rc: RcRef<String> = RcRef::map(stuff_rc, |v| &v.bar);
/// ```
+#[derive(Debug)]
pub struct RcRef<T> {
rc: Rc<dyn Any>,
value: *const T,
@@ -136,7 +137,7 @@ impl<T: 'static> RcRef<T> {
Self::from(Rc::new(value))
}
- pub fn map<S: 'static, R: i::RcLike<S>, F: FnOnce(&S) -> &T>(
+ pub fn map<S: 'static, R: RcLike<S>, F: FnOnce(&S) -> &T>(
source: R,
map_fn: F,
) -> RcRef<T> {
@@ -144,6 +145,11 @@ impl<T: 'static> RcRef<T> {
let value = map_fn(unsafe { &*value });
RcRef { rc, value }
}
+
+ pub(crate) fn split(rc_ref: &Self) -> (&T, &Rc<dyn Any>) {
+ let &Self { ref rc, value } = rc_ref;
+ (unsafe { &*value }, rc)
+ }
}
impl<T: Default + 'static> Default for RcRef<T> {
@@ -152,6 +158,21 @@ impl<T: Default + 'static> Default for RcRef<T> {
}
}
+impl<T> Clone for RcRef<T> {
+ fn clone(&self) -> Self {
+ Self {
+ rc: self.rc.clone(),
+ value: self.value,
+ }
+ }
+}
+
+impl<T: 'static> From<&RcRef<T>> for RcRef<T> {
+ fn from(rc_ref: &RcRef<T>) -> Self {
+ rc_ref.clone()
+ }
+}
+
impl<T: 'static> From<Rc<T>> for RcRef<T> {
fn from(rc: Rc<T>) -> Self {
Self {
@@ -161,12 +182,9 @@ impl<T: 'static> From<Rc<T>> for RcRef<T> {
}
}
-impl<T> Clone for RcRef<T> {
- fn clone(&self) -> Self {
- Self {
- rc: self.rc.clone(),
- value: self.value,
- }
+impl<T: 'static> From<&Rc<T>> for RcRef<T> {
+ fn from(rc: &Rc<T>) -> Self {
+ rc.clone().into()
}
}
@@ -189,8 +207,18 @@ impl<T> AsRef<T> for RcRef<T> {
}
}
+/// The `RcLike` trait provides an abstraction over `std::rc::Rc` and `RcRef`,
+/// so that applicable methods can operate on either type.
+pub trait RcLike<T>: AsRef<T> + Into<RcRef<T>> {}
+
+impl<T: 'static> RcLike<T> for Rc<T> {}
+impl<T: 'static> RcLike<T> for RcRef<T> {}
+impl<T: 'static> RcLike<T> for &Rc<T> {}
+impl<T: 'static> RcLike<T> for &RcRef<T> {}
+
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<T> AsyncRefCell<T> {
/// 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<AsyncRefCell<T>>,
- >(
- cell: &R,
+ /// `None`.
+ pub fn borrow_sync<M: BorrowModeTrait, R: RcLike<AsyncRefCell<T>>>(
+ cell: R,
) -> Option<AsyncBorrowImpl<T, M>> {
+ 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::<T, M>::new(cell.clone().into()))
+ cell_ref.borrow_count.get().try_add(M::borrow_mode())?;
+ cell_ref.borrow_count.set(new_borrow_count);
+ Some(AsyncBorrowImpl::<T, M>::new(cell.into()))
} else {
None
}
@@ -359,10 +384,10 @@ mod internal {
}
impl<T, M: BorrowModeTrait> AsyncBorrowFutureImpl<T, M> {
- pub fn new<R: RcLike<AsyncRefCell<T>>>(cell: &R) -> Self {
+ pub fn new<R: RcLike<AsyncRefCell<T>>>(cell: R) -> Self {
Self {
- cell: Some(cell.clone().into()),
- id: cell.create_waiter::<M>(),
+ id: cell.as_ref().create_waiter::<M>(),
+ 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<T>: Clone + Deref<Target = T> + Into<RcRef<T>> {}
-
- impl<T: 'static> RcLike<T> for Rc<T> {}
- impl<T: 'static> RcLike<T> for RcRef<T> {}
}
#[cfg(test)]