C++20新特性—coroutine协程(一)

本文介绍了C++20中新增的协程特性,包括协程的基本概念、运行机制和相关关键字如co_return、co_yield、co_await。通过示例解释了协程函数的构造、promise_type以及协程状态的管理,展示了如何使用协程实现异步操作的同步编写方式。
摘要由CSDN通过智能技术生成

所谓“协程”,简单点说就是一个函数可以中止运行,待“条件成熟”后,再次在断点的地方重新运行,即能以“进入-暂停-继续-暂停…”这样的方式运行函数,因此讨论协程,需要关心下面几个问题:

  • 在运行点暂停,然后再运行—暂停点的记录
  • 暂停时的运行环境,恢复运行时,应首先恢复当时的环境—运行环境的记录
  • 因协程状态是变化的,因此需要有办法查询协程当前的运行状态,包括返回值、异常等—协程状态的记录

异步操作是 “慢”资源与“快”资源协调编程方面的一个“老”问题,协程的目标就是试图以“同步的形式”编写出异步操作的效果。
以前,C++协程的实现可以通过第三方库来实现的,例如Boost就有两种协程实现(Boost.coroutine2中的协程和Boost.Asio中的协程,见笔者的博文),现在,协程从语言标准层面得以支持,也就是不需要第三方库了。
C++20增加了库<coroutine>,需要协程支持时应包含该文件(【注】gcc10.2编译时需要添加-fcoroutines)。
C++的协程是无栈(stackless)协程,与一个协程关联的有三个对象:
一个promise_type内部对象,保存协程的结果(或发生的异常)
一个handle,从外部可以用来恢复执行或销毁协程
一个可保存coroutine state的内部对象,从堆中分配空间(因而是stackless),包括以下内容:

  • 所有的函数参数(值参数和引用参数,这里需要注意的是引用参数,如果协程的生命期比被引用的参数长,则这些引用参数会因不可用而变得很“危险”)
  • 当前中断点
  • 那些跨越中断点前后的(局部)变量

为表达协程,C++引入了三个关键字:co_return,co_yield和co_await。
co_await:一元操作符。co_await用法为co_await expr,其中expr需要满足一定条件(即awaitable),它要含有以下三个函数:

bool await_ready()
void awai
C++20 引入了一种新的语言特性:协程协程是一种轻量级的、非抢占式的线程,可以实现在同一个线程中切换执行不同的任务,从而避免了线程切换的开销。C++20 中的协程可以通过 co_await 和 co_yield 等关键字来实现。 在 C++20 中创建协程的方式如下: 1. 定义协程函数,使用 co_await 来等待其他协程或异步操作完成: ```c++ #include <coroutine> struct task { struct promise_type { auto initial_suspend() { return std::suspend_never{}; } auto final_suspend() { return std::suspend_never{}; } auto get_return_object() { return task{}; } void return_void() {} void unhandled_exception() {} }; }; task foo() { std::cout << "start\n"; co_await std::suspend_always{}; std::cout << "end\n"; } int main() { foo(); } ``` 2. 使用 co_yield 来暂停当前协程,并返回一个值: ```c++ #include <coroutine> #include <iostream> struct generator { struct promise_type { int current_value; auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() { return std::suspend_always{}; } auto get_return_object() { return generator{this}; } auto yield_value(int value) { current_value = value; return std::suspend_always{}; } void return_void() {} void unhandled_exception() {} }; generator(promise_type* p) : coro(std::coroutine_handle<promise_type>::from_promise(*p)) {} ~generator() { if (coro) coro.destroy(); } generator(const generator&) = delete; generator& operator=(const generator&) = delete; generator(generator&& other) noexcept : coro(other.coro) { other.coro = nullptr; } generator& operator=(generator&& other) noexcept { if (this != &other) { coro = other.coro; other.coro = nullptr; } return *this; } int next() { coro.resume(); return coro.promise().current_value; } private: std::coroutine_handle<promise_type> coro; }; generator range(int from, int to) { for (int i = from; i < to; ++i) { co_yield i; } } int main() { for (auto i : range(0, 5)) { std::cout << i << '\n'; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值