Рассмотрим следующий код:
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
в сопрограмме.
Coroutines TS Говорит, что resume
можно вызвать только тогда, когда сопрограмма приостановлена.
Считается ли он приостановленным во время исполнения await_suspend
?
Да, текст связанных TS сопрограмм гласит, 5.3.8 пункт 3-5. Акцент мой:
5 Выражение await оценивает выражение готовности к ожиданию, затем:
(5.1) Если результат ложный, сопрограмма считается приостановленной. Затем вычисляется выражение await-suspend. Если
это выражение имеет тип bool и оценивается как false, сопрограмма
возобновляется. Если это выражение выходит через исключение, исключение
пойман, сопрограмма возобновлена, и исключение немедленно
повторно брошенный (15.1). В противном случае поток управления возвращается к текущему.
вызывающий или возобновляющий (8.4.4) без выхода из области (6.6). —
Таким образом, вы можете возобновить сопрограмму из другого потока, если вы гарантируете, что выход из await-suspend не приведет к двойному возобновлению или разрушению сопрограммы
Других решений пока нет …