blob: 6994def16a1da3f537c9fb78bdc4a8622c2d13d5 [file] [log] [blame]
use std::future::*;
use std::marker::PhantomPinned;
use std::pin::*;
use std::ptr;
use std::task::*;
struct Delay {
delay: usize,
}
impl Delay {
fn new(delay: usize) -> Self {
Delay { delay }
}
}
impl Future for Delay {
type Output = ();
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
if self.delay > 0 {
self.delay -= 1;
Poll::Pending
} else {
Poll::Ready(())
}
}
}
fn mk_waker() -> Waker {
use std::sync::Arc;
struct MyWaker;
impl Wake for MyWaker {
fn wake(self: Arc<Self>) {
unimplemented!()
}
}
Waker::from(Arc::new(MyWaker))
}
async fn do_stuff() {
(&mut Delay::new(1)).await;
}
// Same thing implemented by hand
struct DoStuff {
state: usize,
delay: Delay,
delay_ref: *mut Delay,
_marker: PhantomPinned,
}
impl DoStuff {
fn new() -> Self {
DoStuff {
state: 0,
delay: Delay::new(1),
delay_ref: ptr::null_mut(),
_marker: PhantomPinned,
}
}
}
impl Future for DoStuff {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
unsafe {
let this = self.get_unchecked_mut();
match this.state {
0 => {
// Set up self-ref.
this.delay_ref = &mut this.delay;
// Move to next state.
this.state = 1;
Poll::Pending
}
1 => {
let delay = &mut *this.delay_ref;
Pin::new_unchecked(delay).poll(cx)
}
_ => unreachable!(),
}
}
}
}
fn run_fut<T>(fut: impl Future<Output = T>) -> T {
let waker = mk_waker();
let mut context = Context::from_waker(&waker);
let mut pinned = pin!(fut);
loop {
match pinned.as_mut().poll(&mut context) {
Poll::Pending => continue,
Poll::Ready(v) => return v,
}
}
}
fn self_referential_box() {
let waker = mk_waker();
let cx = &mut Context::from_waker(&waker);
async fn my_fut() -> i32 {
let val = 10;
let val_ref = &val;
let _ = Delay::new(1).await;
*val_ref
}
fn box_poll<F: Future>(
mut f: Pin<Box<F>>,
cx: &mut Context<'_>,
) -> (Pin<Box<F>>, Poll<F::Output>) {
let p = f.as_mut().poll(cx);
(f, p)
}
let my_fut = Box::pin(my_fut());
let (my_fut, p1) = box_poll(my_fut, cx);
assert!(p1.is_pending());
let (my_fut, p2) = box_poll(my_fut, cx);
assert!(p2.is_ready());
drop(my_fut);
}
fn main() {
run_fut(do_stuff());
run_fut(DoStuff::new());
self_referential_box();
}