从使用角度解读c++20 协程_c++20 协程
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
协程长什么样子
网上一堆乱七八糟的定义看的人云里雾里毫无意义。下面从实战角度看看协程到底长什么样子。
首先类比线程线程是个函数。把这个函数交给 创建线程的api然后这个函数就变成线程了。这个函数本身没有任何特殊的地方就是普通函数。
相比于线程协程也是个函数不过协程函数比线程函数讲究多了。
- 它必须要有返回值返回值的类型 还必须’内嵌’一个promise_type类型
- promise_type类型 还必须 至少包含几个特定的实现
返回值类型最简如下
struct task {
struct promise_type {
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void unhandled_exception() noexcept {}
task get_return_object() noexcept { return {}; }
};
};
从表现形式上说下面就是个最简协程函数
task do_by_coroutine() {}
c++20的协程三板斧
co_await、co_return、co_yield。
这3个关键字是用来控制协程运行的那么自然只能在协程函数里面使用。他们到底是用来干什么的
co_return
最简单最好理解的。普通函数返回用return协程函数返回用co_return没什么稀奇的含义很好理解。但是用起来又比较讲究。
- 如果协程函数返回’void’那么promise_type类型需要对应加一个return_void实现
struct task {
struct promise_type {
...
void return_void() noexcept {} //for co_return void
};
};
- 如果协程函数返回’值’那么promise_type类型需要对应加一个return_value实现 比如返回一个字符串形参v就是返回的’值’
struct task {
struct promise_type {
...
void return_value(std::string&& v) noexcept {} //for co_return value
};
};
co_yield
co_yield其实没必要去深入理解它它其实是co_await的一个’变体糖’。co_yield expr 会被转化为 co_await promise.yield_value(expr)本质还是co_await。
同样co_yield用起来也比较讲究。挂起协程同时返回一个值promise_type类型需要对应加一个yield_value实现比如返回一个字符串形参from就是返回的’值’
struct task {
struct promise_type {
...
std::suspend_always yield_value(std::string&& from) noexcept{ //for co_yield value
value_ = std::move(from);
return {};
}
std::string value_;
};
};
co_await
最后一个同时也是最讲究的关键字。
co_await expr从这个expr必须可以得到awaitable对象。到底什么是awaitable包含以下3个特定实现的就是awaitable最简的awaitable定义如下
struct awaitable {
bool await_ready() noexcept { return false; }
std::string await_resume() noexcept { return "123"; };
void await_suspend(std::coroutine_handle<> h) noexcept {};
};
最简单的使用方式
auto value = co_await awaiter{};
上述语句怎么和awaitable的3个实现关联起来的
- 首先调用await_ready根据返回值来控制协程运行。
- 如果返回值false则会调用await_suspend挂起协程形参h表示协程对象可以用来控制协程。
- 如果返回值true则会调用await_resume返回"123"给value不过await_ready通常为false因为需要主动控制协程。
- 第2步中挂起协程后可以调用resume在合适的时机恢复协程运行调用resume后await_resume会被调用返回"123"给value。
- 主要是步骤1->2->4await_resume返回值也可以为空。
理解协程
协程函数必须要有返回值且返回值类型必须符合特定要求这个点比线程函数讲究多了。
协程三板斧关键字 也必须符合对应要求才可以使用。co_return对应return_void或者return_valueco_yield对应yield_valueco_await对应awaitable。
写点简单的示例代码单纯从使用角度上来理解协程其实就这么点东西。