clone values for Futures

This commit is contained in:
Greg Johnston 2024-02-17 16:50:23 -05:00
parent 4df42cbc60
commit 201adb7406
2 changed files with 18 additions and 15 deletions

View file

@ -135,8 +135,11 @@ impl<T: Send + Sync + 'static> DefinedAt for AsyncDerived<T> {
} }
} }
impl<T: Send + Sync + Clone + 'static> IntoFuture for AsyncDerived<T> { impl<T: Send + Sync + Clone + 'static> IntoFuture for AsyncDerived<T>
type Output = ReadGuard<T, Mapped<Plain<AsyncState<T>>, T>>; where
T: Clone,
{
type Output = T;
type IntoFuture = AsyncDerivedFuture<T>; type IntoFuture = AsyncDerivedFuture<T>;
#[track_caller] #[track_caller]

View file

@ -44,8 +44,11 @@ pub struct AsyncDerivedFuture<T> {
wakers: Arc<RwLock<Vec<Waker>>>, wakers: Arc<RwLock<Vec<Waker>>>,
} }
impl<T: 'static> IntoFuture for ArcAsyncDerived<T> { impl<T> IntoFuture for ArcAsyncDerived<T>
type Output = ReadGuard<T, Mapped<Plain<AsyncState<T>>, T>>; where
T: Clone + 'static,
{
type Output = T;
type IntoFuture = AsyncDerivedFuture<T>; type IntoFuture = AsyncDerivedFuture<T>;
fn into_future(self) -> Self::IntoFuture { fn into_future(self) -> Self::IntoFuture {
@ -57,8 +60,13 @@ impl<T: 'static> IntoFuture for ArcAsyncDerived<T> {
} }
} }
impl<T: 'static> Future for AsyncDerivedFuture<T> { // this is implemented to output T by cloning it because read guards should not be held across
type Output = ReadGuard<T, Mapped<Plain<AsyncState<T>>, T>>; // .await points, and it's way too easy to trip up by doing that!
impl<T> Future for AsyncDerivedFuture<T>
where
T: Clone + 'static,
{
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let waker = cx.waker(); let waker = cx.waker();
@ -70,15 +78,7 @@ impl<T: 'static> Future for AsyncDerivedFuture<T> {
self.wakers.write().or_poisoned().push(waker.clone()); self.wakers.write().or_poisoned().push(waker.clone());
Poll::Pending Poll::Pending
} }
AsyncState::Complete(_) => { AsyncState::Complete(value) => Poll::Ready(value.clone()),
Poll::Ready(ReadGuard::new(Mapped::new(value, |inner| {
match inner {
AsyncState::Complete(value) => value,
// we've just checked this value is Complete
_ => unreachable!(),
}
})))
}
} }
} }
} }