Skip to content

Instantly share code, notes, and snippets.

@Minoru
Created August 14, 2020 14:35
Show Gist options
  • Save Minoru/556e51936dd9f2dcc92e053c3eb066ea to your computer and use it in GitHub Desktop.
Save Minoru/556e51936dd9f2dcc92e053c3eb066ea to your computer and use it in GitHub Desktop.
use async_std::task::block_on;
use async_std::task::{sleep, spawn};
use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
pin_project! {
struct TwoFutures<Fut1, Fut2> {
first_done: bool,
#[pin]
first: Fut1,
#[pin]
second: Fut2,
}
}
impl<Fut1: Future, Fut2: Future> Future for TwoFutures<Fut1, Fut2> {
type Output = Fut2::Output;
fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let this = self.project();
if !*this.first_done {
if let Poll::Ready(_) = this.first.poll(ctx) {
*this.first_done = true;
}
}
if *this.first_done {
this.second.poll(ctx)
} else {
Poll::Pending
}
}
}
fn sleepus() -> impl Future<Output = ()> {
TwoFutures {
first_done: false,
first: sleep(Duration::from_millis(3000)),
// The blog post suggests to use an ordinary block here,
// but that prints the message *upon construction*.
// A better approach is to construct a future here,
// so the printing is delayed until the moment
// when the future is polled.
second: {
async_std::future::poll_fn(|_ctx| {
println!("Hello TwoFutures");
Poll::Ready(())
})
},
}
}
async fn interruptus() {
for i in 1..=5 {
println!("Interruptus {}", i);
sleep(Duration::from_millis(1000)).await;
}
}
fn main() {
block_on(async {
let sleepus = spawn(sleepus());
interruptus().await;
sleepus.await;
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment