Coroutine Scenarios

Generator

  • 可以挂起返回很多值
  • 当挂起的caller恢复运行时,使用value
  • Lazy sequence
  • 实现iterator/sentinel
// C++23实现该标准库
std::generator<uint64_t>
fibonacci_sequence(unsigned n) {
if (n > 0) co_yield 0;
if (n > 1) co_yield 1;
uint64_t a = 0, b = 1;
for (unsigned i = 2; i < n; ++i) {
uint64_t s = a+b;
co_yield s;
a = b;
b = s;
}
}

Task

  • 类似函数调用的感觉

  • Caller co_await当task被创建

  • task<T>::await_suspend()存放caller-handle(in its promise)同时开始callee

  • The stored handle is called the continuation

  • task<T>::final_suspend()resumes the continuation

Asynchronous I/O

  • await_suspend()stores the coroutine_handle<> and registers a callback with the OS

  • The callback will put results in the Awaiter and resume()the coroutine

  • await_resume()provides the results to the coroutine

char data[1024];
while(1) {
size_t n = co_await inSocket.async_read(buffer(data));
co_await async_write(outSocket, buffer(data, n));
}

Scheduler

  • act as an Awaitable
  • 所有的actors 定期co_await
struct Scheduler {
std::list<std::coroutine_handle<>> _tasks{};

bool schedule() {
auto task = _tasks.front();
_tasks.pop_front();

if (not task.done()) {
task.resume();
}
return not _tasks.empty();
}
auto suspend() {
struct awaiter : std::suspend_always {
Scheduler &_sched;
explicit awaiter(Scheduler &sched) : _sched{sched} {}
bool await_ready() { return false; }
void await_suspend(std::coroutine_handle<> hdl) const noexcept {
_sched._tasks.push_back(hdl);
}
void await_resume() {}
};
return awaiter{*this};
}
};