Skip to content

Commit 8cf0785

Browse files
Thomasdezeeuwcramertj
authored andcommitted
Add Future::interleave_pending
1 parent 06e2d98 commit 8cf0785

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

futures-test/src/future/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use futures_core::future::Future;
1010
use futures_executor;
1111
use std::thread;
1212

13+
pub use crate::interleave_pending::InterleavePending;
14+
1315
/// Additional combinators for testing futures.
1416
pub trait FutureTestExt: Future {
1517
/// Asserts that the given is not moved after being polled.
@@ -79,6 +81,34 @@ pub trait FutureTestExt: Future {
7981
{
8082
thread::spawn(|| futures_executor::block_on(self));
8183
}
84+
85+
/// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending)
86+
/// in between each call to poll.
87+
///
88+
/// # Examples
89+
///
90+
/// ```
91+
/// #![feature(async_await)]
92+
/// use futures::task::Poll;
93+
/// use futures::future::{self, Future};
94+
/// use futures_test::task::noop_context;
95+
/// use futures_test::future::FutureTestExt;
96+
/// use pin_utils::pin_mut;
97+
///
98+
/// let future = future::ready(1).interleave_pending();
99+
/// pin_mut!(future);
100+
///
101+
/// let mut cx = noop_context();
102+
///
103+
/// assert_eq!(future.as_mut().poll(&mut cx), Poll::Pending);
104+
/// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(1));
105+
/// ```
106+
fn interleave_pending(self) -> InterleavePending<Self>
107+
where
108+
Self: Sized,
109+
{
110+
InterleavePending::new(self)
111+
}
82112
}
83113

84114
impl<Fut> FutureTestExt for Fut where Fut: Future {}

futures-test/src/interleave_pending.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use futures_core::future::Future;
12
use futures_core::stream::Stream;
23
use futures_io::{self as io, AsyncBufRead, AsyncRead, AsyncWrite};
34
use pin_utils::{unsafe_pinned, unsafe_unpinned};
@@ -63,6 +64,27 @@ impl<T> InterleavePending<T> {
6364
}
6465
}
6566

67+
impl<Fut: Future> Future for InterleavePending<Fut> {
68+
type Output = Fut::Output;
69+
70+
fn poll(
71+
mut self: Pin<&mut Self>,
72+
cx: &mut Context<'_>,
73+
) -> Poll<Self::Output> {
74+
if *self.as_mut().pended() {
75+
let next = self.as_mut().inner().poll(cx);
76+
if next.is_ready() {
77+
*self.pended() = false;
78+
}
79+
next
80+
} else {
81+
cx.waker().wake_by_ref();
82+
*self.pended() = true;
83+
Poll::Pending
84+
}
85+
}
86+
}
87+
6688
impl<St: Stream> Stream for InterleavePending<St> {
6789
type Item = St::Item;
6890

0 commit comments

Comments
 (0)