Выражения await
Syntax
AwaitExpression → Expression . await
Выражение await - это синтаксическая конструкция для приостановки вычисления,
предоставляемого реализацией std::future::IntoFuture, до тех пор, пока данное
будущее (future) не будет готово произвести значение.
Синтаксис выражения await: выражение с типом, который реализует трейт IntoFuture, называемое операндом будущего, затем токен ., и затем ключевое слово await.
Выражения await разрешены только внутри асинхронного контекста, такого как async fn, async замыкание или async блок.
Более конкретно, выражение await имеет следующий эффект.
- Создает будущее, вызывая
IntoFuture::into_futureна операнде будущего. - Вычисляет будущее до будущего
tmp; - Фиксирует
tmpс помощьюPin::new_unchecked; - Это зафиксированное будущее затем опрашивается путем вызова метода
Future::pollи передачи ему текущего контекста задачи; - Если вызов
pollвозвращаетPoll::Pending, то будущее возвращаетPoll::Pending, приостанавливая свое состояние так, что когда окружающий асинхронный контекст переопрашивается, выполнение возвращается к шагу 3; - В противном случае вызов
pollдолжен был вернутьPoll::Ready, в этом случае значение, содержащееся в вариантеPoll::Ready, используется как результат самого выраженияawait.
2018 Edition differences
Выражения await доступны только начиная с Rust 2018.
Контекст задачи
Контекст задачи относится к Context, который был предоставлен текущему асинхронному контексту, когда сам асинхронный контекст был опрошен.
Поскольку выражения await разрешены только в асинхронном контексте, должен быть доступен некоторый контекст задачи.
Приблизительная десугаризация
Фактически, выражение await примерно эквивалентно следующей ненормативной десугаризации:
match operand.into_future() {
mut pinned => loop {
let mut pin = unsafe { Pin::new_unchecked(&mut pinned) };
match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) {
Poll::Ready(r) => break r,
Poll::Pending => yield Poll::Pending,
}
}
}
где псевдокод yield возвращает Poll::Pending и, при повторном вызове, возобновляет выполнение с этой точки.
Переменная current_context ссылается на контекст, взятый из асинхронного окружения.