Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Выражения await

Syntax
AwaitExpressionExpression . await

Выражение await - это синтаксическая конструкция для приостановки вычисления, предоставляемого реализацией std::future::IntoFuture, до тех пор, пока данное будущее (future) не будет готово произвести значение.

Синтаксис выражения await: выражение с типом, который реализует трейт IntoFuture, называемое операндом будущего, затем токен ., и затем ключевое слово await.

Выражения await разрешены только внутри асинхронного контекста, такого как async fn, async замыкание или async блок.

Более конкретно, выражение await имеет следующий эффект.

  1. Создает будущее, вызывая IntoFuture::into_future на операнде будущего.
  2. Вычисляет будущее до будущего tmp;
  3. Фиксирует tmp с помощью Pin::new_unchecked;
  4. Это зафиксированное будущее затем опрашивается путем вызова метода Future::poll и передачи ему текущего контекста задачи;
  5. Если вызов poll возвращает Poll::Pending, то будущее возвращает Poll::Pending, приостанавливая свое состояние так, что когда окружающий асинхронный контекст переопрашивается, выполнение возвращается к шагу 3;
  6. В противном случае вызов 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 ссылается на контекст, взятый из асинхронного окружения.