Boost Coroutine2 - stackful coroutine简介
协程可以很轻量的在子例程中进行切换,它由程序员进行子例程的调度(即切换)而不像线程那样需要内核参与,同时也省去了内核线程切换的开销,因为一个协程切换保留的就是函数调用栈和当前指令的寄存器,而线程切换需要陷入内核态,改变线程对象状态。
go把协程作为基础设施提供语言级的支持,cpp这种出了名的给程序员自由的语言肯定不会提供语言级的支持,而是通过准标准库boost coroutine2库(boost coroutine已经废弃,建议使用boost coroutine2)为cpp提供的协程支持。
这里有个来自boost coroutine2的例子可以说明协程的好处。假设有两个函数
(图片来自boost_1_65_1/libs/coroutine2/doc/html/coroutine2/intro.html)
协程可以在两个子例程之前轻松切换交错输出,不使用协程就就需要把两个子例程拆分成更小的子例程,如果期间涉及依赖上下文的计算那么拆分也不行,只能考虑setjump/longjump或者线程等解决方案,显然这样一来脑力复杂度,代码复杂度也就上来了。
协程分为对称协程(symmetric)和非对称协程(asymmetric),对称协程需要显式指定将控制权yeild给谁,非对称协程可以隐式的转移控制权给它的调用者,boost coroutine2实现的是非对称协程。
现在来实现上图的效果:
#include <iostream>
#include <boost/coroutine2/all.hpp> void foo(boost::coroutines2::coroutine<void>::push_type & sink){
std::cout << "a ";
sink();
std::cout << "b ";
sink();
std::cout << "c ";
} int main(){
boost::coroutines2::coroutine<void>::pull_type source(foo);
std::cout << "1 ";
source();
std::cout << "2 ";
source();
std::cout << "3 ";
getchar();
return ;
}
如果把push pull反过来会得到相反的输出:
void foo(boost::coroutines2::coroutine<void>::pull_type & sink1){
std::cout << "a ";
sink1();
std::cout << "b ";
sink1();
std::cout << "c ";
} int main(){
boost::coroutines2::coroutine<void>::push_type source(foo);
std::cout << "1 ";
source();
std::cout << "2 ";
source();
std::cout << "3 ";
return ;
}
模板参数为void的协程是特例化的实现,它比之普通的泛型协程少了get()和迭代器实现。
这里我们使用带返回值的协程,然后用get方法获取它的返回值:
#include <iostream>
#include <boost/coroutine2/all.hpp> void foo(boost::coroutines2::coroutine<std::string>::pull_type & sink){
std::cout << "get " << sink.get() << "from main() by foo()\n";
sink();
std::cout << "get " << sink.get() << "from main() by foo()\n";
sink();
} int main(){
std::string str1("HELLO");
std::string str2("WORLD");
boost::coroutines2::coroutine<std::string>::push_type source(foo);
std::cout << "pass " << str1 << " from main() to foo()\n";
source(str1);
std::cout << "pass " << str2 << " from main() to foo()\n";
source(str2);
return ;
}
不难看出push可以传入参数,pull可以接受参数。
现在再试试协程的迭代器,对了,协程的迭代器不支持后置++:
#include <iostream>
#include <boost/coroutine2/all.hpp>
#include <boost/coroutine2/detail/push_coroutine.hpp>
#include <boost/coroutine2/detail/pull_coroutine.hpp> constexpr int N = ; // 方法一:中规中矩
void foo(boost::coroutines2::coroutine<int>::pull_type & sink){
using coIter = boost::coroutines2::coroutine<int>::pull_type::iterator;
for (coIter start = begin(sink); start != end(sink); ++start) {
std::cout << "retrieve "<<*start << "\n";
}
}
// 方法二:auto自动推导
void foo2(boost::coroutines2::coroutine<int>::pull_type & sink) {
for (auto val : sink) {
std::cout << "retrieve " << val << "\n";
}
}
// 方法三:守旧
void foo3(boost::coroutines2::coroutine<int>::pull_type & sink) {
for (int i = ; i < N; i++) {
std::cout << "retrieve " << sink.get() << "\n";
sink();
}
} int main(){
boost::coroutines2::coroutine<int>::push_type source(foo2);
for (int i = ; i < N; i++) {
source(i);
}
return ;
}
Boost Coroutine2 - stackful coroutine简介的更多相关文章
- Boost.Coroutine2:学习使用Coroutine(协程)
function(函数)routine(例程)coroutine (协程) 函数,例程以及协程都是指一系列的操作的集合. 函数(有返回值)以及例程(没有返回值)也被称作subroutine(子例程), ...
- Boost LRU-Cache使用方法简介
缓存是提高系统运行效率的常用组件,可以将"有效的"业务数据直接返回用户,避免繁琐的计算过程.除了Redis.MemCache等常用缓存系统,应用程序内部也可以根据需要设置一定容量的 ...
- boost Asio网络编程简介
:first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...
- Boost - 从Coroutine2 到Fiber
Boost - 从Coroutine2 到Fiber 协程引子 我开始一直搞不懂协程是什么,网上搜一搜,(尤其是Golang的goroutine)感觉从概念上听起来有点像线程池,尤其是类似Java的E ...
- Visual studio 2017编译 boost
下载: https://www.boost.org/ 或者 https://dl.bintray.com/boostorg/release/1.66.0/source/ 下载完成以后解压到自己想要 ...
- Array的简单使用(Boost和STL通用)
目录 目录 介绍 使用 Boost和STL的区别 介绍 本来这一次是想简单介绍一下Boost里面的协程库的使用的,但是Boost.Coroutine已经被废弃了,而Boost.Coroutine2目前 ...
- C++17尝鲜
https://cloud.tencent.com/developer/article/1351910 [译]C++17,optional, any, 和 variant 的更多细节 用户261520 ...
- Golang源码探索(二) 协程的实现原理
Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱, 虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻 ...
- Golang源码探索(二) 协程的实现原理(转)
Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底 ...
随机推荐
- AES加密实现
起因 这段时间因为要对接一个外部接口,其参数的加密方式为AES,就需要学下AES的加密写法,但网上的资料不是很全,自己记录下遇到的坑: 基本写法 String str = "hello&qu ...
- Linq学习系列-----1.1 Lambda表达式介绍
1.1 Lambda表达式介绍 下图就是一个典型的Lambda表达式. instance:输入参数 =>:Lambda操作符 instance.MemoryCount>=20*1024 ...
- Java数据结构和算法(三)——冒泡、选择、插入排序算法
上一篇博客我们实现的数组结构是无序的,也就是纯粹按照插入顺序进行排列,那么如何进行元素排序,本篇博客我们介绍几种简单的排序算法. 1.冒泡排序 这个名词的由来很好理解,一般河水中的冒泡,水底刚冒出来的 ...
- 详解卷积神经网络(CNN)在语音识别中的应用
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:侯艺馨 前言 总结目前语音识别的发展现状,dnn.rnn/lstm和cnn算是语音识别中几个比较主流的方向.2012年,微软邓力和俞栋老 ...
- 面试相关-转载-well,yzl——持续更新
转载yl,yzl大神的面经,顺便自己复习一下专业课的内容 操作系统相关: 什么是进程, 什么是线程.它们之间的区别和联系. 进程管理内存资源+运行过程, 线程只管理运行过程, 线程要在进程提供的资源基 ...
- VMWare安装Win10虚拟机
这两天突发奇想安了个win10虚拟机,在安装的过程中还遇到了不少麻烦,所以在此与大家分享下. 首先我们用VMWare12来安装,VMWare已经更新到14但是不太稳定,所以为了保险起见还是用12吧. ...
- Numpy入门 - 数组基本运算
本节主要讲解numpy数组的基本运算,包括两数组相加.相减.相乘和相除. 一.两数组相加add import numpy as np arr1 = np.array([[1, 2, 3], [4, 5 ...
- 一道JS 连续赋值运算的问题
原文链接:https://www.cnblogs.com/joesbell/p/6229423.html <script> var a = {n:1}; var b = a; a.x = ...
- react入门到进阶(三)
一.react样式 1.内联样式 在以前写html+css的时候,引入css的时候有一种方法就是内联,而在react中又有些不一样,样式是用变量的形式,如下 const styleComponentH ...
- 关路灯,洛谷dp
题目传送门https://www.luogu.org/problem/show?pid=1220 我们假设 dpij0 为目前最优值是在 i 位置,dpij1 为目前最优值是在 j 位置则 i 到 j ...