Могу ли я вызвать coroutine_handle::resume во время await_suspend?

Рассмотрим следующий код:

coroutine_handle<> g_handle;
atomic<int> g_ready;

void worker_thread() {
  if (++g_ready == 2) g_handle.resume();
}

struct Awaitable {
  bool await_ready() const { return false; }
  bool await_suspend(coroutine_handle<> h) {
    g_handle = h;
    if (++g_ready == 2) return false;
    // worker_thread can call h.resume() at this point
    return true;
  }
  void await_resume() {}
};

Future coroutine() {
  Awaitable a;
  std::thread(worker_thread).detach();
  co_await a; // compiles as:
              // if (a.await_suspend(h)) {
              //   // worker_thread can call h.resume() at this point
              //   return;
              // }
}

Здесь worker_thread может позвонить h.resume(); когда сопрограмма еще выполняется await_suspend или между await_suspend() а также return в сопрограмме.

TS Coroutines говорит, что resume можно вызвать только тогда, когда сопрограмма приостановлена.

Считается ли он приостановленным во время исполнения await_suspend?

1 ответ

Да, текст связанных TS сопрограмм гласит, 5.3.8 пункт 3-5. Акцент мой:

5 Выражение await оценивает выражение готовности к ожиданию, затем:

(5.1) Если результат ложный, сопрограмма считается приостановленной. Затем вычисляется выражение await-suspend. Если это выражение имеет тип bool и имеет значение false, сопрограмма возобновляется. Если это выражение завершается через исключение, исключение перехватывается, сопрограмма возобновляется, и исключение немедленно перебрасывается (15.1). В противном случае поток управления возвращается к текущему вызывающему или возобновляющему абоненту (8.4.4) без выхода из каких-либо областей (6.6). -

Таким образом, вы можете возобновить сопрограмму из другого потока, если вы гарантируете, что выход из await-suspend не приведет к двойному возобновлению или разрушению сопрограммы

Другие вопросы по тегам