141 lines
3.7 KiB
C++
141 lines
3.7 KiB
C++
#include <iostream>
|
|
#include <coroutine>
|
|
|
|
//【概况】
|
|
//1.协程主要用于异步操作编程。
|
|
//2.协程本质上与普通函数调用基本没区别,不同的地方是协程状态会在堆上分配而不是调用栈让它具有了随时暂停、继续执行的功能。
|
|
//3.函数体内出现了co_await、co_return、co_yield任意一个操作符就认为该函数是协程函数。
|
|
|
|
//【使用】
|
|
//1.协议:协程函数必须得有返回值。
|
|
//2.协议:返回类型必须内嵌 promise_type 类型。
|
|
//3.协议:内嵌的 promise_type 必须实现至少几个特定项
|
|
// A.initial_suspend
|
|
// B.final_suspend
|
|
// C.unhandled_exception
|
|
// D.get_return_object
|
|
//4.调用:co_return 用于协程函数的返回
|
|
// 如果返回 void 则内嵌的 promise_type 还必须实现
|
|
// E.return_void
|
|
// 如果返回值类型 则内嵌的 promise_type 还必须实现
|
|
// F.return_value(T&& t) noexcept
|
|
//5.调用:co_yield 其实是 co_await 的变体糖
|
|
// co_yield exp --> co_await promise.yield_value(exp)
|
|
// co_yield 挂起协程同时返回一个值,内嵌的 promise_type 还必须实现
|
|
// G.yield_value
|
|
//6.调用:co_await exp 必须能得到一个 awaitable 对象。
|
|
// 包含以下三个特定实现的就是 awaitable 对象。
|
|
// A.bool await_ready
|
|
// B.T await_resume
|
|
// C.void await_suspend(std::coroutine_handle<> handle)
|
|
|
|
//【梳理】
|
|
// 1.首先调用 await_ready,看返回值。
|
|
// 2. false --> 调用 await_suspend 挂起协程,形参 handle 表示协程对象,可以用来控制协程。
|
|
// true --> 调用 await_resume 返回值。
|
|
// 3.第2步中,若 false 挂起之后,可以调用 await_resume
|
|
|
|
template<typename T>
|
|
struct SimpleGenerator
|
|
{
|
|
struct promise_type;
|
|
using coroutine_handle = std::coroutine_handle<promise_type>;
|
|
|
|
// 生成器的状态
|
|
enum class State { Ready, Done };
|
|
|
|
// 生成器的promise类型
|
|
struct promise_type {
|
|
T value{};
|
|
State state = State::Ready;
|
|
|
|
//在协程开始的时候挂起
|
|
auto initial_suspend() const noexcept {
|
|
return std::suspend_always{};
|
|
}
|
|
|
|
//在协程结束的时候挂起
|
|
auto final_suspend() const noexcept {
|
|
return std::suspend_always{};
|
|
}
|
|
|
|
SimpleGenerator get_return_object() {
|
|
return SimpleGenerator{ coroutine_handle::from_promise(*this) };
|
|
}
|
|
|
|
void return_void() {}
|
|
|
|
auto yield_value(T val) noexcept {
|
|
value = val;
|
|
state = State::Ready;
|
|
return std::suspend_always{};
|
|
}
|
|
|
|
void unhandled_exception() {
|
|
std::terminate();
|
|
}
|
|
};
|
|
|
|
// 构造函数
|
|
SimpleGenerator(coroutine_handle handle) : coro(handle) {}
|
|
|
|
// 禁止拷贝和移动
|
|
SimpleGenerator(const SimpleGenerator&) = delete;
|
|
SimpleGenerator& operator=(const SimpleGenerator&) = delete;
|
|
|
|
SimpleGenerator(SimpleGenerator&& other) noexcept : coro(other.coro) {
|
|
other.coro = nullptr;
|
|
}
|
|
|
|
SimpleGenerator& operator=(SimpleGenerator&& other) noexcept {
|
|
if (this != &other) {
|
|
coro = other.coro;
|
|
other.coro = nullptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
// 析构函数
|
|
~SimpleGenerator() {
|
|
if (coro)
|
|
coro.destroy();
|
|
}
|
|
|
|
// 检查生成器是否完成
|
|
bool done() const {
|
|
return coro && coro.done();
|
|
}
|
|
|
|
// 重载运算符*,以获取当前生成器的值
|
|
T& operator*() {
|
|
return coro.promise().value;
|
|
}
|
|
|
|
// 重载++运算符,以继续生成器的执行
|
|
void operator++() {
|
|
if (!done())
|
|
coro.resume();
|
|
}
|
|
|
|
private:
|
|
coroutine_handle coro;
|
|
};
|
|
|
|
// 一个简单的生成器函数
|
|
SimpleGenerator<int> Counter(int start, int end) {
|
|
for (int i = start; i <= end; ++i) {
|
|
co_yield i;
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
auto gen = Counter(1, 5);
|
|
|
|
while (!gen.done()) {
|
|
std::cout << *gen << std::endl;
|
|
++gen;
|
|
}
|
|
|
|
return 0;
|
|
}
|