Created
October 2, 2021 08:28
-
-
Save jakobrs/d10539e40856ba297bd552d156c4a3fe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use pin_project::*; | |
use pin_utils::*; | |
use std::future::Future; | |
use std::ops::{Deref, DerefMut}; | |
use std::pin::Pin; | |
use std::task::Context; | |
use std::task::Poll; | |
async fn with_context<F, A>(f: F) -> A | |
where | |
F: for<'a, 'b> FnOnce(&'a mut Context<'b>) -> A, | |
{ | |
#[pin_project] | |
struct WithContext<F>(Option<F>); | |
impl<F, A> Future for WithContext<F> | |
where | |
F: for<'a, 'b> FnOnce(&'a mut Context<'b>) -> A, | |
{ | |
type Output = A; | |
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<A> { | |
let f = self.project().0; | |
match std::mem::take(f) { | |
Some(f) => Poll::Ready(f(cx)), | |
None => panic!("WithContext polled after returning Poll::Ready"), | |
} | |
} | |
} | |
WithContext(Some(f)).await | |
} | |
// Like tokio::task::yield_now, but doesn't call the waker | |
async fn yields() { | |
struct Yields(bool); | |
impl Future for Yields { | |
type Output = (); | |
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { | |
match self.0 { | |
false => { | |
self.0 = true; | |
//cx.waker().wake_by_ref(); | |
Poll::Pending | |
} | |
true => Poll::Ready(()), | |
} | |
} | |
} | |
Yields(false).await | |
} | |
async fn poll_async<F>(future: Pin<&mut F>) -> Poll<F::Output> | |
where | |
F: Future, | |
{ | |
with_context(|cx| future.poll(cx)).await | |
} | |
async fn poll_async_mut<F, P>(future: &mut Pin<P>) -> Poll<F::Output> | |
where | |
P: Deref<Target = F> + DerefMut, | |
F: Future, | |
{ | |
poll_async(future.as_mut()).await | |
} | |
#[tokio::main] | |
async fn main() { | |
let sleep = tokio::time::sleep(tokio::time::Duration::from_secs(1)); | |
pin_mut!(sleep); | |
loop { | |
let poll_res = poll_async(sleep.as_mut()).await; | |
match poll_res { | |
Poll::Ready(a) => { | |
println!("{:?}", a); | |
break; | |
} | |
Poll::Pending => { | |
println!("Pending"); | |
yields().await; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment