Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FutureExt::also_poll #2840

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions futures-util/src/future/future/also_poll.rs
@@ -0,0 +1,46 @@
use core::pin::Pin;
use futures_core::future::{FusedFuture, Future};
use futures_core::task::{Context, Poll};
use pin_project_lite::pin_project;

use super::Fuse;

pin_project! {
/// Future for the [`also_poll`](super::FutureExt::also_poll) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct AlsoPoll<Fut, Also> {
#[pin] fut: Fut,
#[pin] also: Fuse<Also>,
}
}

impl<Fut, Also> AlsoPoll<Fut, Also> {
pub(super) fn new(fut: Fut, also: Also) -> Self {
AlsoPoll { fut, also: Fuse::new(also) }
}
}

impl<Fut, Also> Future for AlsoPoll<Fut, Also>
where
Fut: Future,
Also: Future<Output = ()>,
{
type Output = Fut::Output;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let _ = this.also.poll(cx);
this.fut.poll(cx)
}
}

impl<Fut, Also> FusedFuture for AlsoPoll<Fut, Also>
where
Fut: FusedFuture,
Also: Future<Output = ()>,
{
fn is_terminated(&self) -> bool {
self.fut.is_terminated()
}
}
50 changes: 50 additions & 0 deletions futures-util/src/future/future/mod.rs
Expand Up @@ -112,6 +112,9 @@ mod shared;
#[cfg(feature = "std")]
pub use self::shared::{Shared, WeakShared};

mod also_poll;
pub use also_poll::AlsoPoll;

impl<T: ?Sized> FutureExt for T where T: Future {}

/// An extension trait for `Future`s that provides a variety of convenient
Expand Down Expand Up @@ -599,4 +602,51 @@ pub trait FutureExt: Future {
_ => None,
}
}

/// While polling this future, also poll another future at the same time,
/// ensuring progress is made on it.
///
/// The `also` future will be polled alongside the `self` future, in a
/// similar way to `join()`, but if `self` finishes first, `also` will
/// just be cancelled. If `also` finishes first, it will simply no longer
/// be polled.
///
/// Note that if `also_poll` is being called in a loop with the same
/// future, you should take care to ensure that the future is fused in some
/// way, or else repeatedly calling it may cause panics.
///
/// # Examples
///
/// ```
/// # use futures::prelude::*;
/// # futures::executor::block_on(async {
/// use futures::future::maybe_done;
///
/// // this may be something that we do not want to leave unpolled or
/// // half-polled while we're in our loop.
/// let task = maybe_done(async {
/// // ...
/// });
/// futures::pin_mut!(task);
///
/// for x in [1, 2, 3] {
/// do_thing(x).also_poll(&mut task).await;
/// }
///
/// (&mut task).await;
/// let result = task.take_output().unwrap();
/// # let _ = result;
/// # async fn do_thing(_x: i32) -> i32 { 0 }
/// # })
/// ```
///
/// (For the above example, simply using `join()` would likely be best, but
/// that may not be feasible in more complex scenarios.)
fn also_poll<Also>(self, also: Also) -> AlsoPoll<Self, Also>
where
Self: Sized,
Also: Future<Output = ()>,
{
assert_future::<Self::Output, _>(AlsoPoll::new(self, also))
}
}
3 changes: 2 additions & 1 deletion futures-util/src/future/mod.rs
Expand Up @@ -21,7 +21,8 @@ pub use futures_task::{FutureObj, LocalFutureObj, UnsafeFutureObj};
#[allow(clippy::module_inception)]
mod future;
pub use self::future::{
Flatten, Fuse, FutureExt, Inspect, IntoStream, Map, MapInto, NeverError, Then, UnitError,
AlsoPoll, Flatten, Fuse, FutureExt, Inspect, IntoStream, Map, MapInto, NeverError, Then,
UnitError,
};

#[deprecated(note = "This is now an alias for [Flatten](Flatten)")]
Expand Down