[−][src]Macro tokio::pin
Pins a value on the stack.
Calls to async fn
return anonymous Future
values that are !Unpin
.
These values must be pinned before they can be polled. Calling .await
will
handle this, but consumes the future. If it is required to call .await
on
a &mut _
reference, the caller is responsible for pinning the future.
Pinning may be done by allocating with Box::pin
or by using the stack
with the pin!
macro.
The following will fail to compile:
async fn my_async_fn() { // async logic here } #[tokio::main] async fn main() { let mut future = my_async_fn(); (&mut future).await; }
To make this work requires pinning:
use tokio::pin; async fn my_async_fn() { // async logic here } #[tokio::main] async fn main() { let future = my_async_fn(); pin!(future); (&mut future).await; }
Pinning is useful when using select!
and stream operators that require T: Stream + Unpin
.
Usage
The pin!
macro takes identifiers as arguments. It does not work
with expressions.
The following does not compile as an expression is passed to pin!
.
async fn my_async_fn() { // async logic here } #[tokio::main] async fn main() { let mut future = pin!(my_async_fn()); (&mut future).await; }
Examples
Using with select:
use tokio::{pin, select}; use tokio_stream::{self as stream, StreamExt}; async fn my_async_fn() { // async logic here } #[tokio::main] async fn main() { let mut stream = stream::iter(vec![1, 2, 3, 4]); let future = my_async_fn(); pin!(future); loop { select! { _ = &mut future => { // Stop looping `future` will be polled after completion break; } Some(val) = stream.next() => { println!("got value = {}", val); } } } }
Because assigning to a variable followed by pinning is common, there is also a variant of the macro that supports doing both in one go.
use tokio::{pin, select}; async fn my_async_fn() { // async logic here } #[tokio::main] async fn main() { pin! { let future1 = my_async_fn(); let future2 = my_async_fn(); } select! { _ = &mut future1 => {} _ = &mut future2 => {} } }