从使用角度解读c++20 协程示例

目录
  • 协程长什么样子
  • c++20的协程三板斧
    • co_return
    • co_yield
    • co_await
  • 理解协程

协程长什么样子

网上一堆乱七八糟的定义,看的人云里雾里,毫无意义。下面从实战角度看看协程到底长什么样子。

首先,类比线程,线程是个函数。把这个函数交给 创建线程的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->4,await_resume返回值也可以为空。

理解协程

协程函数必须要有返回值,且返回值类型必须符合特定要求,这个点比线程函数讲究多了。

协程三板斧关键字 也必须符合对应要求才可以使用。co_return对应return_void或者return_value,co_yield对应yield_value,co_await对应awaitable。

写点简单的示例代码,单纯从使用角度上来理解协程,其实就这么点东西。

到此这篇关于从使用角度解读c++20 协程示例的文章就介绍到这了,更多相关c++20 协程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++20 特性 协程 Coroutines(1)

    目录 一.协程简单介绍 二.协程的好处 三.协程得用法 四.协程三个关键字 五.协程工作原理 1.co_yield 2.co_return 我们先来介绍一下什么是协程. 一.协程简单介绍 协程和普通的函数 其实差不多. 不过这个 "函数" 能够暂停自己, 也能够被别人恢复. 普通的函数调用, 函数运行完返回一个值, 结束. 协程可以运行到一半, 返回一个值, 并且保留上下文. 下次恢复的时候还可以接着运行, 上下文 (比如局部变量) 都还在. 这就是最大的区别. 二.协程的好处 考虑多

  • 详解c++20协程如何使用

    什么是协程 新接触的人看了网上很多人的见解都是一头雾水,本人的理解,协程就是可中断的函数,这个函数在执行到某一时刻可以暂停,保存当前的上下文(比如当前作用域的变量,函数参数等等),在后来某一时刻可以手动恢复这个中断的函数,把保存的上下文恢复并从中断的地方继续执行.简而言之,协程就是可中断的函数,协程如何实现:保存上下文和恢复上下文. 你可能会说协程不会这么简单的吧,我这里来举例一下啊,如python的协程 def test(): print('begin') yield print('hello

  • C++20中的协程(Coroutine)的实现

    C++20中的协程(Coroutine) 从2017年开始, 协程(Coroutine)的概念就开始被建议加入C++20的标准中了,并已经开始有人对C++20协程的提案进行了介绍.1事实上,协程的概念在很早就出现了,甚至其他语言(JS,Python,C#等)早就已经支持了协程. 可见,协程并不是C++所特有的概念. 那么,什么是协程? 简单来说,协程就是一种特殊的函数,它可以在函数执行到某个地方的时候暂停执行,返回给调用者或恢复者(可以有一个返回值),并允许随后从暂停的地方恢复继续执行.注意,这

  • C++20 新特性 协程 Coroutines(2)

    目录 1.co_await 2.awaiter 的三个接口用途 3.协程用法的回顾 想了解上一篇文章内容的小伙伴可点击 C++20 特性 协程 Coroutines (1) 谈到什么是协程. 并且介绍了 co_yield 和 co_return 的作用. 这篇来介绍一下 co_await. 1.co_await 一个形如: co_await awaitable 的表达式就叫一个 await-expression. co_await 表达式是用来暂停当前协程的运行, 转而等待 awaitable

  • 从使用角度解读c++20 协程示例

    目录 协程长什么样子 c++20的协程三板斧 co_return co_yield co_await 理解协程 协程长什么样子 网上一堆乱七八糟的定义,看的人云里雾里,毫无意义.下面从实战角度看看协程到底长什么样子. 首先,类比线程,线程是个函数.把这个函数交给 创建线程的api,然后这个函数就变成线程了.这个函数本身没有任何特殊的地方,就是普通函数. 相比于线程,协程也是个函数,不过协程函数比线程函数讲究多了. 它必须要有返回值,返回值的类型 还必须’内嵌’一个promise_type类型pr

  • 深入浅析python中的多进程、多线程、协程

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专门的管理和控制执行程序的数据结构--进程控制块. 进程就是一个程序在一个数据集上的一次动态执行过程. 进程一般由程序.数据集.进程控

  • PHP7下协程的实现方法详解

    前言 相信大家都听说过『协程』这个概念吧. 但是有些同学对这个概念似懂非懂,不知道怎么实现,怎么用,用在哪,甚至有些人认为yield就是协程! 我始终相信,如果你无法准确地表达出一个知识点的话,我可以认为你就是不懂. 如果你之前了解过利用PHP实现协程的话,你肯定看过鸟哥的那篇文章:在PHP中使用协程实现多任务调度| 风雪之隅 鸟哥这篇文章是从国外的作者翻译来的,翻译的简洁明了,也给出了具体的例子了. 我写这篇文章的目的,是想对鸟哥文章做更加充足的补充,毕竟有部分同学的基础还是不够好,看得也是云

  • Python并发编程协程(Coroutine)之Gevent详解

    Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporateroutine的缩写,直接翻译为协同的例程,一般我们都简称为协程. 在linux系统中,线程就是轻量级的进程,而我们通常也把协程称为轻量级的线程即微线程. 进程和协程 下面对比一下进程和协程的相同点和不同点: 相同点: 我们都可以把他们看做是一种执行流,执行流可以挂起,并且后面可以在你挂起的地方恢复执行,这实际上都可以看做是con

  • 详解python之协程gevent模块

    Gevent官网文档地址:http://www.gevent.org/contents.html 进程.线程.协程区分 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译为协同的例程,一般我们都简称为协程. 在linux系统中,线程就是轻量级的进程,而我们通常也把协程称为轻量级的线程即微线程. 进程和协程 下面对比一下进程和协程的相同点和不同点: 相同点: 相同点存在于,当我们挂起一个执行流的时,我们要保存的东西: 栈, 其实在你切换前你的局部变量,以及

  • C++通信新特性协程详细介绍

    目录 一.关于协程 二.协程的好处 三.协程得用法 四.与线程的区别 五.协程示例 一.关于协程 从 1.54.0 版本开始,Boost.Asio 支持协程.虽然您可以直接使用 Boost.Coroutine,但 Boost.Asio 中对协程的显式支持使得使用它们变得更加容易. 协程让您创建一个反映实际程序逻辑的结构.异步操作不会拆分函数,因为没有处理程序来定义异步操作完成时应该发生什么.程序可以使用顺序结构,而不是让处理程序相互调用. 二.协程的好处 考虑多任务协作的场景. 如果是线程的并发

随机推荐