Макрос pin
macro_rules! pin {
($($x:ident),*) => { ... };
($(
let $x:ident = $init:expr;
)*) => { ... };
}
Закрепляет значение на стеке.
Вызовы async fn возвращают анонимные значения Future, которые являются !Unpin. Эти значения необходимо закрепить, прежде чем их можно будет опрашивать. Вызов .await сделает это, но потребит future. Если требуется вызвать .await для ссылки &mut _, вызывающий код должен самостоятельно закрепить future.
Закрепить значение можно, выделив память с помощью Box::pin или используя стек с макросом pin!.
Следующий пример не скомпилируется:
async fn my_async_fn() {
// async logic here
}
#[tokio::main]
async fn main() {
let mut future = my_async_fn();
(&mut future).await;
}
Чтобы это заработало, значение необходимо закрепить:
use tokio::pin;
async fn my_async_fn() {
// async logic here
}
let future = my_async_fn();
pin!(future);
(&mut future).await;Закрепление полезно при использовании select! и операторов потоков, которым требуется T: Stream + Unpin.
Использование
Макрос pin! принимает в качестве аргументов идентификаторы. Он не работает с выражениями.
Следующий пример не компилируется, поскольку в pin! передаётся выражение.
async fn my_async_fn() {
// async logic here
}
#[tokio::main]
async fn main() {
let mut future = pin!(my_async_fn());
(&mut future).await;
}
Примеры
Использование с select:
use tokio::{pin, select};
use tokio_stream::{self as stream, StreamExt};
async fn my_async_fn() {
// async logic here
}
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);
}
}
}Поскольку присваивание переменной с последующим закреплением — распространённый сценарий, существует также вариант макроса, который позволяет выполнить оба действия за один раз.
use tokio::{pin, select};
async fn my_async_fn() {
// async logic here
}
pin! {
let future1 = my_async_fn();
let future2 = my_async_fn();
}
select! {
_ = &mut future1 => {}
_ = &mut future2 => {}
}
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/macro.pin.html