Coroutines были введены в стандарт C++20. К сожалению, его реализация не так удобна даже для опытных разработчиков, поскольку стандартная библиотека предоставляет только интерфейсы, а цикл событий, ожидание, обещания и т.д. оставляет на усмотрение программистов.
Это простой рабочий пример, который поможет вам начать обучение:
#include <iostream> #include <coroutine> #include <thread> #include <queue> #include <functional> std::queue<std::function<bool()>> task_queue; struct sleep { sleep(int n) : delay{n} {} constexpr bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> h) const noexcept { auto start = std::chrono::steady_clock::now(); task_queue.push([start, h, d = delay] { if (decltype(start)::clock::now() - start > d) { h.resume(); return true; } else { return false; } }); } void await_resume() const noexcept {} std::chrono::milliseconds delay; }; struct Task { struct promise_type { promise_type() = default; Task get_return_object() { return {}; } std::suspend_never initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() {} }; }; Task foo1() noexcept { std::cout << "1. hello from foo1" << std::endl; for (int i = 0; i < 10; ++i) { co_await sleep{10}; std::cout << "2. hello from foo1" << std::endl; } } Task foo2() noexcept { std::cout << "1. hello from foo2" << std::endl; for (int i = 0; i < 10; ++i) { co_await sleep{10}; std::cout << "2. hello from foo2" << std::endl; } } //call foo int main() { foo1(); foo2(); while (!task_queue.empty()) { auto task = task_queue.front(); if (!task()) { task_queue.push(task); } task_queue.pop(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } }
Волшебство происходит здесь co_await sleep{10};. Текущая корутина приостанавливается, а awaiter принимает ее обработчик, чтобы возобновить ее позже. В этом примере awaiter откладывает задачу в цикл событий, чтобы проверить, не истекло ли время ожидания.
Это простой цикл событий с очередью задач:
while (!task_queue.empty()) { auto task = task_queue.front(); if (!task()) { task_queue.push(task); } task_queue.pop(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
Поиграйте немного с этим примером, прежде чем приступить к подробному изучению Coroutines (корутинов). Надеюсь, это было полезно!
Возможно вам так же будет интересно: