Implementing futures
Implementing futures is very common when using Tokio. Let’s start with a verybasic future that performs no asynchronous logic and simply returns a message(the venerable “hello world”).
The Future trait.
The trait is as follows:
Let’s implement it for our “hello world” future:
The Item
and Error
associated types define the types returned by the futureonce it completes. Item
is the success value and Error
is returned when thefuture encounters an error while processing. By convention, infallible futuresset Error
to ()
.
Futures use a poll based model. The consumer of a future repeatedly calls thepoll
function. The future then attempts to complete. If the future is able tocomplete, it returns Async::Ready(value)
. If the future is unable to completedue to being blocked on an internal resource (such as a TCP socket), it returnsAsync::NotReady
.
The hello world future requires no asynchronous processing and is immediatelyready, so it returns Ok(Async::Ready(value))
.
Running the future
Tokio is responsible for running futures to completion. This is done by passingthe future to tokio::run
.
The tokio::run
accepts futures where both Item
and Error
are set to ()
.This is because Tokio only executes the futures, it does not do anything withvalues. The user of Tokio is required to fully process all values in the future.
In our case, let’s print the future to STDOUT. We will do that by implementing aDisplay
future.
The Display
takes a future that yields items that can be displayed. When it ispolled, it first tries to poll the inner future. If the inner future is notready then Display
cannot complete. In this case, Display
also returns.
The Display
future will error when the inner future errors. The error isbubbled up.
When HelloWorld
is combined with Display
, both the Item
and Error
typesare ()
and the future can be executed by Tokio:
Running this results in “hello world” being outputted to standard out.
Cleaning things up
The pattern of waiting on an inner future is common enough that there is ahelper macro: try_ready!
.
The poll function can be rewritten using the macro as such: