#include <iostream>
#include <thread>
#include <coroutine>
#include <chrono>
#include <functional>
// g++-10 -std=c++2a coroutineDemo.cpp -fcoroutines -lpthread
using call_back = std::function<void(int)>;
void Add100ByCallback(int init, call_back f) // 异步调用
{
std::thread t([init, f]() {
std::this_thread::sleep_for(std::chrono::seconds(5));
f(init + 100);
});
t.detach();
}
struct Add100AWaitable
{
Add100AWaitable(int init) :init_(init) {}
bool await_ready() const { return false; }
int await_resume() { return result_; }
void await_suspend(std::coroutine_handle<> handle)
{
auto f = [handle, this](int value) mutable {
result_ = value;
handle.resume();
};
Add100ByCallback(init_, f); // 调用原来的异步调用
}
int init_;
int result_;
};
struct Task
{
struct promise_type {
auto get_return_object() { return Task{}; }
auto initial_suspend() { return std::suspend_never{}; }
auto final_suspend() noexcept { return std::suspend_never{}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
};
};
Task Add100ByCoroutine(int init, call_back f)
{
int ret = co_await Add100AWaitable(init);
ret = co_await Add100AWaitable(ret);
ret = co_await Add100AWaitable(ret);
f(ret);
}
int main()
{
Add100ByCoroutine(10, [](int value) { std::cout << "get result from coroutine1: " << value << "\n"; });
Add100ByCoroutine(20, [](int value) { std::cout << "get result from coroutine2: " << value << "\n"; });
Add100ByCoroutine(30, [](int value) { std::cout << "get result from coroutine3: " << value << "\n"; });
Add100ByCoroutine(40, [](int value) { std::cout << "get result from coroutine4: " << value << "\n"; });
}
如果要实现形如co_await blabla;
的协程调用格式, blabla就必须实现Awaitable。co_await
是一个新的运算符。Awaitable主要有3个函数:
1. await_ready
:返回Awaitable实例是否已经ready。协程开始会调用此函数,如果返回true,表示你想得到的结果已经得到了,协程不需要执行了。所以大部分情况这个函数的实现是要return false。
2. await_suspend
:挂起awaitable。该函数会传入一个coroutine_handle
类型的参数。这是一个由编译器生成的变量。在此函数中调用handle.resume(),就可以恢复协程。
3. await_resume
:当协程重新运行时,会调用该函数。这个函数的返回值就是co_await
运算符的返回值。
文章引用:c++20协程入门 - 知乎
代码我进行了修正和改进。
有问题,可以一起交流。