Skip to content

Commit

Permalink
address fuse code review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
glendc committed May 8, 2024
1 parent 6c220b9 commit b9f736d
Showing 1 changed file with 32 additions and 29 deletions.
61 changes: 32 additions & 29 deletions src/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,31 @@ where
}
}

/// Fuse a future such that `poll` will never again be called once it has
/// completed. This method can be used to turn any `Future` into a
/// `FusedFuture`.
///
/// Normally, once a future has returned `Poll::Ready` from `poll`,
/// any further calls could exhibit bad behavior such as blocking
/// forever, panicking, never returning, etc. If it is known that `poll`
/// may be called too often then this method can be used to ensure that it
/// has defined semantics.
///
/// If a `fuse`d future is `poll`ed after having returned `Poll::Ready`
/// previously, it will return `Poll::Pending`, from `poll` again (and will
/// continue to do so for all future calls to `poll`).
///
/// This combinator will drop the underlying future as soon as it has been
/// completed to ensure resources are reclaimed as soon as possible.
pub fn fuse<F>(future: F) -> Fuse<F>
where
F: Future + Sized,
{
Fuse::new(future)
}

pin_project! {
/// [`Future`] for the [`fuse`](super::FutureExt::fuse) method.
/// [`Future`] for the [`fuse`] method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Fuse<Fut> {
Expand All @@ -473,13 +496,16 @@ impl<Fut: Future> Future for Fuse<Fut> {
type Output = Fut::Output;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output> {
match self.as_mut().project().inner.as_pin_mut() {
Some(fut) => fut.poll(cx).map(|output| {
self.as_mut()
.project()
.inner
.as_pin_mut()
.map(|f| f.poll(cx))
.unwrap_or(Poll::Pending)
.map(|output| {
self.project().inner.set(None);
output
}),
None => Poll::Pending,
}
})
}
}

Expand Down Expand Up @@ -686,29 +712,6 @@ pub trait FutureExt: Future {
}
}

/// Fuse a future such that `poll` will never again be called once it has
/// completed. This method can be used to turn any `Future` into a
/// `FusedFuture`.
///
/// Normally, once a future has returned `Poll::Ready` from `poll`,
/// any further calls could exhibit bad behavior such as blocking
/// forever, panicking, never returning, etc. If it is known that `poll`
/// may be called too often then this method can be used to ensure that it
/// has defined semantics.
///
/// If a `fuse`d future is `poll`ed after having returned `Poll::Ready`
/// previously, it will return `Poll::Pending`, from `poll` again (and will
/// continue to do so for all future calls to `poll`).
///
/// This combinator will drop the underlying future as soon as it has been
/// completed to ensure resources are reclaimed as soon as possible.
fn fuse(self) -> Fuse<Self>
where
Self: Sized,
{
Fuse::new(self)
}

/// Returns the result of `self` or `other` future, with no preference if both are ready.
///
/// Each time [`Race`] is polled, the two inner futures are polled in random order. Therefore,
Expand Down

0 comments on commit b9f736d

Please sign in to comment.