Действительно ли пробудить будущее Rust во время опроса? - PullRequest
6 голосов
/ 29 января 2020

Я бы хотел спать в своем будущем за один «кадр», чтобы могла случиться другая работа. Является ли это правильной реализацией этой идеи?

use std::future::Future;
use std::task::{Context, Poll};
use std::pin::Pin;

struct Yield {
    yielded: bool,
}

impl Future for Yield {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<()> {
        if self.yielded {
            Poll::Ready(())
        } else {
            self.yielded = true;

            // This is the part I'm concerned about
            ctx.waker().wake_by_ref();

            Poll::Pending
        }
    }
}

В частности, меня беспокоит то, что контекст не "заметит" вызов wake_by_ref, если он сделан до того, как опрос вернет Pending. Предоставляет ли контракт интерфейса poll какие-либо гарантии того, что эта задача будет немедленно повторно опрошена при выполнении таким способом?

1 Ответ

2 голосов
/ 30 января 2020

TL; DR: Ваш код действителен.

На основании контракта с мастером, он должен опросить ваше будущее еще раз. В противном случае возможно иметь состояние состязания между вызовом Future::poll и партнером будущего, который фактически выполняет некоторую работу.

Давайте рассмотрим пример:

impl Future for Foo {
    type Output = ();
    fn poll(self: Pin<&mut Self>, ctx: &mut Context) -> Poll<()> {
        let result = communicate_with_worker(ctx); // returns false

        // <-- Time point (1)

        return match result {
            true => Poll::Pending,
            false => Poll::Ready(()),
        };
    }
}

В момент времени (1) будущее решило, что оно не готово, но возможно, что поток опроса здесь приостановлен, и рабочий поток был запланирован и завершил свою работу.

Рабочий поток затем вызовет waker и запросит опрос в будущем. Если бродяга решил не опрашивать будущее снова, так как он опрашивает будущее прямо сейчас, то он никогда больше не получит запрос на пробуждение.

Это означает, что бродяга может отклонить запросы на пробуждение, которые поступили раньше * Был вызван номер 1015 *, но нельзя отклонять запросы на пробуждение, поступившие во время будущего вызова poll.


Единственный вопрос, который у меня возник: почему вы хотите перенести опрос еще на один кадр ?

Поскольку ваша фактическая работа должна выполняться в отдельном потоке (а не внутри fn poll), то нет смысла переносить опрос.

...