协程和 C++ Boost库的Coroutine2

news2024/11/18 15:51:52

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

协程和 C++ Boost库的Coroutine2

  • 摘要
    • 为什么不是boost.coroutine?
  • 线程与协程
    • 为什么不介绍C++20标准的协程
    • C++协程与golang的goroutine
  • 二、使用步骤
    • 1.引入库
    • 2.核心类
    • 单个协程
    • 两个协程交叉执行


摘要

协程是一种轻量级的并发单位,相比于线程,它具有更小的内存占用和更高效的调度,适用于I/O密集型和计算密集型场景。Boost.Coroutine2是一种协程实现,它是一种特殊控制流,允许在某些位置暂停和恢复执行的子例程。它保留了本地执行状态,并允许重入子例程多次。然而,Boost.Coroutine2的多个实例是顺序执行的,不支持并行执行。在并发性能和资源利用率方面,Goroutine相比于Coroutine2具有更优秀的表现。因此,在编写并发程序时,建议根据实际需求选择适合的并发模型和相应的语言机制。Boost.Coroutine2适用于多个任务的协助和生成器模式等场景。


为什么不是boost.coroutine?

boost官方团队已经声明现已弃用,推荐使用coroutine2。

线程与协程

线程

线程是操作系统提供的一种并发执行的机制,它具有以下特点:

运行在系统态,由操作系统调度。
线程实例之间各自独立运行,共享堆内存,栈空间是各自独占的。
一个初始线程会占用几兆内存,即便它没做什么。
线程之间的切换需要一定的开销。
有完善的同步锁、数据共享机制。

协程

协程是轻量级的并发模型,它具有以下特点:

运行在用户态,由程序员自己调度。
协程实例之间共享堆内存和栈空间。
一个初始协程只占用几KB内存。
协程之间的切换开销极小。
需要开发人员自己实现同步机制。

为什么不介绍C++20标准的协程

C++20引入了无栈协程的特性,为更好的开发异步编程做好了准备。但是由于该版本的协程实现方法一直有很大的争议,协程通过决议的时间很晚,所以实际仅提供了三个关键字来支持协程实现,真正想用协程还要自己实现协程库。然后来不及在C++20中提供协程相关的支持库,像std::generator、std::task等等,需要在C++23中才能提供,有了这些库的支持,基本可以使用标准库的协程了,C++23太新了,编译器的支持当前还没跟上,另外它的实现和使用跟coroutine2差异很小,所以我可能会继续选择使用coroutine2。

C++协程与golang的goroutine

coroutine2跟goroutine不一样,它实际上无法并行

Goroutine是Go语言中轻量级的并发单位,它由Go运行时系统管理和调度,能够在多核处理器上并行执行。而Coroutine2则是一种协程,它是由用户代码自行调度和管理的轻量级线程,通常只在一个线程中顺序执行或者交替,不支持并行执行。

Goroutine相比于Coroutine2具有更小的内存占用和更高效的调度,因此在并发性能和资源利用率方面更加优秀。Go语言通过Goroutine和Channel等机制,提供了一种简洁而高效的并发编程范式,使得开发人员能够轻松地编写并发的程序。

需要注意的是,虽然Coroutine2本身不支持并行执行,但通过一些技术手段可以将Coroutine2组合成并发的执行流,例如使用线程池或者协程池等方式来并发执行Coroutine2。但是这种方式的并发性能和资源利用率相比Goroutine可能会有所下降。

这样比较下看coroutine2对协程的实现好像很鸡肋,但其实goroutine与coroutine行为上的不用也表明了它们的应用场景也不同:
Boost.Coroutine2 可以被视为boost提供的一种特殊控制流,允许在某些位置暂停和恢复执行的子例程。 它保留了本地执行状态,并允许重入子例程多次(如果必须在函数调用之间保持状态,则很有用)。如(生成器、协作式多任务处理)都是它适合的场景,代码结构很简介,这部分优于goroutine。

在这里插入图片描述

二、使用步骤

1.引入库

依赖库:Boost.Context
需要语言版:C++11版本
头文件位置:#include <boost/coroutine2/all.hpp>

2.核心类

coroutine2中只有两个核心的类:pull_type,push_type。

在 Boost.Coroutine2 中,协程只能单向传递数据,数据只能单向的从一个代码块流向另一个代码块。流入流出分别对应着 push_type 和 pull_type 类型,由这两个类型组成协程间跳转的通道,同时也是数据传递的通道。

pull_type

pull_type 用于从协程中获取数据,它提供了以下方法:
begin():返回一个迭代器,可以迭代获取协程中的数据。
get():获取协程中的下一个数据。
operator():调用协程的下一个操作,并返回协程是否结束。

push_type

push_type 用于向协程中传递数据,它提供了以下方法:
operator():向协程中传递数据,并返回协程是否结束。

单个协程

	/*
	 * 斐波那契数列
	 */
	boost::coroutines2::coroutine<int>::pull_type source(
		[&](boost::coroutines2::coroutine<int>::push_type& sink) {
		int first = 1, second = 1;
		sink(first);
		sink(second);
		for (int i = 0; i<8; ++i) {
			int third = first + second;
			first = second;
			second = third;
			sink(third);
		}
	});

	for (auto i : source)
	{
		std::cout << i << " ";

	}

输出:1 1 2 3 5 8 13 21 34 55

两个协程交叉执行

	boost::coroutines2::coroutine<int>::pull_type apull([](boost::coroutines2::coroutine<int>::push_type& apush)
	{
		for (int i = 0; i < 10; i++)
		{
			cout << "---------------------" << "coroutine 1" << endl;
			apush(1);
		}

	}
	);


	boost::coroutines2::coroutine<int>::pull_type apull2([](boost::coroutines2::coroutine<int>::push_type& apush)
	{

		for (int i = 0; i < 10; i++)
		{
			cout << "---------------------" << "coroutine 2" << endl;
			apush(2);
		}

	}
	);

	for (int i = 0; i < 10; ++i)
	{
		apull.get();
		apull();
		apull2.get();
		apull2();
	}
	cout << "continue>>>" << endl;

输出:

---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
---------------------coroutine 1
---------------------coroutine 2
continue>>>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1129288.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

作为程序员,很多时候容易急眼,如何缓解?

程序员在工作中面临着高压和快节奏的环境&#xff0c;容易因为紧张的工作节奏、复杂的技术问题或与团队的沟通问题而感到焦虑和急躁。下面提供一些策略来帮助缓解这种情况&#xff1a; 1. 定时休息 遵循“番茄工作法”或其他时间管理技术&#xff0c;每工作25分钟后休息5分钟&…

“第四十九天” 机组

各个硬件的工作原理&#xff1a; 主存储器包括&#xff1a;存储体、MAR、MDR&#xff1b; MAR&#xff1a;存储地址寄存器 &#xff0c;MAR的位数反映存储单元的个数&#xff1b; MDR &#xff1a; 存储数据存储器&#xff0c;MDR位数等于存储字长&#xff1b; 数据在存储体…

【Opencv】OpenCV使用CMake和MinGW的编译安装出错解决

编译时出现的错误&#xff1a; mingw32-make[1]: *** [modules/core/CMakeFiles/opencv_core.dir/all] Error 2 Makefile:161: recipe for target ‘all’ failed mingw32-make: *** [all] Error 2解决方法&#xff1a; 根据贴吧老哥的解答&#xff0c;发现是mingw版本有问题导…

合并有序链表C++递归

题目描述 21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; 解题思路 我们这里使用递归的思路来解题&#xff1a; 首先我们要分析题目的子问题在哪&#xff0c;对于这个问题我们先思考如何将两个只有一个节点的有序单链表合并&#xff1a; ①我们可以先判断哪一个…

DCU上如何运行大模型以及用到的docker命令

第一步&#xff1a;需要连接到官方(https://developer.hpccube.com/)提供的vpn 第二步&#xff1a;通过termius进入到项目 第三步&#xff1a;遇到问题 1.docker空间太小了&#xff0c;得换地方&#xff1a;参考这个centos设置docker 目录_mob64ca12f73101的技术博客_51CTO博…

寻找特殊年号

系列文章目录 进阶的卡莎C_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(C…

正点原子嵌入式linux驱动开发——Linux INPUT子系统

按键、鼠标、键盘、触摸屏等都属于输入(input)设备&#xff0c;Linux内核为此专门做了一个叫做input子系统的框架来处理输入事件。输入设备本质上还是字符设备&#xff0c;只是在此基础上套上了input框架&#xff0c;用户只需要负责上报输入事件&#xff0c;比如按键值、坐标等…

python二次开发Solidworks:读取样条曲线数据

目录 1、草图段对象 2、VBA代码分析 3、python代码实现 样条曲线&#xff08;spline curve&#xff09;是数学术语&#xff0c;是一种特殊的参数曲线&#xff0c;由一组控制点通过曲线拟合的方式生成。样条一词源于船舶建造中的一种临时性辅助支架&#xff0c;后来被引入计算…

基于卷的磁盘扫描算法设计

1、设计目的 常规情况下&#xff0c;当我们扫描计算机的硬盘时&#xff0c; 通常会使用诸如FindFirstFile/FindNextFile(Windows)&#xff0c;或者opendir/readdir(Linux)遍历扫描的目录。 一般情形下&#xff0c;由于文件数量相对较少&#xff0c;文件夹层次低&#xff0c;扫…

Hafnium简介和构建

安全之安全(security)博客目录导读 目录 一、Hafnium简介 二、Hafnium构建 2.1.1 先决条件 2.1.1.1 构建Host 2.1.1.2 工具链 2.1.1.3 依赖 2.1.1.4 获取源码 2.1.2 构建 一、Hafnium简介 可信固件为Armv8-A、Armv9-A和Armv8-M提供了安全软件的参考实现。它为SoC开发人…

MSVCR100.dll丢失修复方法,MSVCR100.dll丢失的解决方法

今天我要和大家分享的是&#xff1a;msvcr100.dll丢失的6种解决方法。 首先&#xff0c;让我们来了解一下msvcr100.dll丢失的原因。msvcr100.dll是Microsoft Visual C 2010的一个组件&#xff0c;它包含了许多运行库文件&#xff0c;这些文件是许多应用程序所必需的。当msvcr1…

TouchGFX界面开发 | 图像控件应用示例

图像控件应用示例 TouchGFX中的图像会绘制关联图像文件中的像素数据。 使用图像文件前&#xff0c;必须将其导入到项目中。TouchGFX Designer内置了五种类型的图像部件&#xff1a; 固定图像&#xff1a;图像大小是由关联的图像文件定义的&#xff0c;不能在运行时改动。若要将…

物联网AI MicroPython传感器学习 之 GPS户外定位模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; 一、产品简介 HT2828Z3G5L是一款高性能的面向车载组合导航领域的定位G-MOUSE&#xff0c;系统包含同时支持北斗和GPS的高性能卫星接收机芯片。具备全方位功能&#xff0c;能满足专业定位的严格要求。体积小巧…

【数据结构】常见复杂度习题详解 ------ 习题篇

文章目录 &#x1f4cb;前言一. ⛳️前篇回顾二. ⛳️常见时间复杂度计算举例1️⃣实例一2️⃣实例二3️⃣实例三4️⃣实例四5️⃣实例五6️⃣实例六7️⃣实例七8️⃣实例八 三. ⛳️常见空间复杂度计算举例1️⃣实例一2️⃣实例二3️⃣实例三 四. ⛳️总结 &#x1f4cb;前言 …

GIS 数据结构整理:网格索引

1 一维网格索引 把整个数据库数值空间划分成n*n的正方形网格&#xff0c;建立另一个倒排文件——栅格索引每一个网格在栅格索引中有一个索引条目(记录)&#xff0c;在这个记录中登记所有位于或穿过该网格的物体的关键字 1.1 变长指针法 在这个网格的物体&#xff0c;按照序号…

2023年系统设计面试如何破解?进入 FAANG 面试的实战指南

如果您正在准备编码面试&#xff0c;但想知道如何准备关键的系统设计主题&#xff0c;并寻找正确方法、技巧和问题的分步指导&#xff0c;那么您来对地方了。在本文中&#xff0c;我将分享 2023 年系统设计面试的完整指南。 在软件开发领域&#xff0c;如果您正在申请高级工程…

『Linux升级路』权限管理

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、Linux中的用户 &#x1f4d2;1.1Linux用户分类 &#x1f4d2;1.2用户转换…

网络编程 day3

#include <head.h> #define SER_PORT 6678 //服务器端口号 #define SER_IP "192.168.115.64"//服务器IP地址 #define CLI_PORT 6666 //客户端端口号 #define CLI_IP "192.168.115.93" int main(int argc, const char *argv[]) {//1.创建套接字,用于连…

css-边框流水线

效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><meta name"viewport" content"initial-scale1.0, user-scalableno" /><title></title><style type&…

eNSP笔记③

密码模式 Telnet ①首先进入console口 [Huawei]user-interface console 0②设置模式为密码模式,回车后输入密码 [Huawei-ui-console0]authentication-mode password ③设置对应权限3 [Huawei-ui-console0]user privilege level 3用户级别允许使用的命令级别进入系统视图保存…