Implement Future

Contract

  • Future is a regular trait which has a method poll
  • poll should return Poll::Ready(...) if you think the Future complets.
  • poll should return Poll::Pending if you think the Future is in progress
  • poll is initially invoked underneath by the async runtime.
  • You need to tell the async runtime to invoke poll again if your Future is in progress. Otherwise, it never complete.

We will use tokio as the async runtime.

Poll::Ready

The program completes immediately.

Poll::Pending

The program never stop.

How do we tell the async runtime invoke poll again?

Use Waker

busy polling

The program keeps polling.

cx.waker().wake_by_ref();

Waker is implemented by tokio

final complete

Finally, the program needs return Poll::Ready.

interval polling

The program keeps interval polling using a thread.

Use OS mechanism

Thread spawning is not costless. We could use OS timer somehow, but it’s a bit of complex to setup OS layer. Luckily, tokio Sleep has already been implemented for us.

  • this is unsafe code

    We declare a heap-allocated pointer first, then convert that to a Pin pointer.

  • this is safe code

    We declare a Pin pointer directly using Box::pin which is type Pin<Box<T>>. Pin<Box<T>> could be converted to Pin<&mut T> using its Box::as_mut method.

For how to use Pin, see pin

Reference

  1. Pin, Unpin, and why Rust needs them
  2. Pin and suffering