当前位置: 首页 > news >正文

C++ 20 协程(一)

C++ 20 协程(一)

介绍

C++ 20提供的是非对称的、一等对象、无栈的协程(Coroutines in C++20 are asymmetric, first-class, and stackless)

所谓协程,即用户级线程,一种用于将异步代码同步化的编程机制,使得程序的执行流可以在多个并行事务之间切换但又不必承担切换带来的过高的性能损耗。当前很多的编程语言都内置协程特性或者有自己的协程库,如C/C++的libco、golang的goroutine等。而在实现机制上,又可以划分为有栈协程和无栈协程

协程是可以在保持状态的同时暂停和恢复执行的函数

image-20220925140527159

非对称协程与对称协程

非对称协程(asymmetric coroutines)是跟一个特定的调用者绑定的,协程让出CPU时,只能让回给原调用者。那到底是什么东西“不对称”呢?第一,非对称在于程序控制流转移到被调协程时使用的是suspend/resume操作,而当被调协程让出 CPU 时使用的却是return/yield操作。第二,协程间的地位也不对等,caller与callee关系是确定的,不可更改的,非对称协程只能返回最初调用它的协程。微信团队的libco其实就是一种非对称协程,Boost C++库也提供了非对称协程。另外,挂起(suspend)和恢复(resume)跟yield的区别是:yield后的协程,之后还会被切换回来,但是被suspend挂起的协程,除非调用resume()恢复它,否则永远不会再被执行到。在不同语言中,这三者会有不同的叫法,比如call也会调用新函数时也会同时实现suspend旧函数的功能,有的语言用yield/resume和return,不一而论,但区别不变。

对称协程(symmetric coroutines)则不同,被调协程启动之后就跟之前运行的协程没有任何关系了。协程的切换操作,一般而言只有一个操作yield或return,用于将程序控制流转移给另外的协程。对称协程机制一般需要一个调度器的支持,按一定调度算法去选择yield或return的目标协程。Go语言提供的协程,其实就是典型的对称协程。不但对称,goroutines还可以在多个线程上迁移。这种协程跟操作系统中的线程非常相似,甚至可以叫做“用户级线程”。

一等对象(第一类对象)

[python - What are “first-class” objects? - Stack Overflow](https://stackoverflow.com/questions/245192/what-are-first-class-objects

第一类对象(英语:First-class object)在计算机科学中指可以在执行期创造并作为参数传递给其他函数或存入一个变量的实体[1]。将一个实体变为第一类对象的过程叫做“物件化”(Reification)[2]。

无栈协程

有栈(stackful)协程通常的实现手段是在堆上提前分配一块较大的内存空间(比如 64K),也就是协程所谓的“栈”,参数、return address 等都可以存放在这个“栈”空间上。如果需要协程切换,那么通过 swapcontext 一类的形式来让系统认为这个堆上空间就是普通的栈,这就实现了上下文的切换。

有栈协程最大的优势就是侵入性小,使用起来非常简便,已有的业务代码几乎不需要做什么修改,但是 C++20 最终还是选择了使用无栈协程,主要出于下面这几个方面的考虑。

无栈协程是一个可以暂停和恢复的函数,是函数调用的泛化。

我们知道一个函数的函数体(function body)是顺序执行的,执行完之后将结果返回给调用者,我们没办法挂起它并稍后恢复它,只能等待它结束。而无栈协程则允许我们把函数挂起,然后在任意需要的时刻去恢复并执行函数体,相比普通函数,协程的函数体可以挂起并在任意时刻恢复执行。

img

所以,从这个角度来说,无栈协程是普通函数的泛化。

总结一下,有栈协程是用户态线程,无栈协程就是函数调用

相关文章:

  • 小米手机抓取hci log
  • 【Java深入学习】并发常见方法的注意事项
  • 微信小程序开发入门与实战(数据监听)
  • 【论文阅读】提升的自动作文评分通过Prompt预测和匹配
  • JPA-Specification常用条件查询构造方式
  • 瑞吉外卖(19) - 新增套餐业务开发
  • Android 的定位分层架构
  • 基于docker搭建es集群
  • 2.可视化基础(上)
  • 解决Vue项目中ESLint和Prettier冲突问题[Vue.js项目实践: 新冠自检系统]
  • 【misc】buu-面具下的flag——zip伪加密+用NTFS流隐藏文件
  • java毕业设计企业安全与设备管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  • Message Bus Solace Deeper Dive
  • Android-AGP之手写你的第一款自定义plugin插件
  • 入门力扣自学笔记159 C++ (题目编号788)
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【刷算法】从上往下打印二叉树
  • HashMap ConcurrentHashMap
  • java中具有继承关系的类及其对象初始化顺序
  • js
  • JS 面试题总结
  • JSDuck 与 AngularJS 融合技巧
  • nodejs实现webservice问题总结
  • node学习系列之简单文件上传
  • PHP 小技巧
  • Sequelize 中文文档 v4 - Getting started - 入门
  • session共享问题解决方案
  • 大快搜索数据爬虫技术实例安装教学篇
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 对象引论
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 删除表内多余的重复数据
  • 深度学习入门:10门免费线上课程推荐
  • 详解NodeJs流之一
  • 用jquery写贪吃蛇
  • 用简单代码看卷积组块发展
  • Linux权限管理(week1_day5)--技术流ken
  • Semaphore
  • 大数据全解:定义、价值及挑战
  • #每天一道面试题# 什么是MySQL的回表查询
  • (C语言)fread与fwrite详解
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (四)汇编语言——简单程序
  • (转)nsfocus-绿盟科技笔试题目
  • .form文件_SSM框架文件上传篇
  • .gitignore文件设置了忽略但不生效
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .Net Winform开发笔记(一)
  • .net开发引用程序集提示没有强名称的解决办法
  • // an array of int
  • :not(:first-child)和:not(:last-child)的用法
  • @JsonSerialize注解的使用
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!