Boost Coroutine2 - stackful coroutine简介

时间:2021-08-26 17:50:11

协程可以很轻量的在子例程中进行切换,它由程序员进行子例程的调度(即切换)而不像线程那样需要内核参与,同时也省去了内核线程切换的开销,因为一个协程切换保留的就是函数调用栈和当前指令的寄存器,而线程切换需要陷入内核态,改变线程对象状态。

go把协程作为基础设施提供语言级的支持,cpp这种出了名的给程序员*的语言肯定不会提供语言级的支持,而是通过准标准库boost coroutine2库(boost coroutine已经废弃,建议使用boost coroutine2)为cpp提供的协程支持。

这里有个来自boost coroutine2的例子可以说明协程的好处。假设有两个函数

Boost Coroutine2 - stackful coroutine简介

(图片来自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简介的更多相关文章

  1. Boost&period;Coroutine2:学习使用Coroutine(协程)

    function(函数)routine(例程)coroutine (协程) 函数,例程以及协程都是指一系列的操作的集合. 函数(有返回值)以及例程(没有返回值)也被称作subroutine(子例程), ...

  2. Boost LRU-Cache使用方法简介

    缓存是提高系统运行效率的常用组件,可以将"有效的"业务数据直接返回用户,避免繁琐的计算过程.除了Redis.MemCache等常用缓存系统,应用程序内部也可以根据需要设置一定容量的 ...

  3. boost Asio网络编程简介

    :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...

  4. Boost - 从Coroutine2 到Fiber

    Boost - 从Coroutine2 到Fiber 协程引子 我开始一直搞不懂协程是什么,网上搜一搜,(尤其是Golang的goroutine)感觉从概念上听起来有点像线程池,尤其是类似Java的E ...

  5. Visual studio 2017编译 boost

    下载: https://www.boost.org/   或者 https://dl.bintray.com/boostorg/release/1.66.0/source/ 下载完成以后解压到自己想要 ...

  6. Array的简单使用(Boost和STL通用)

    目录 目录 介绍 使用 Boost和STL的区别 介绍 本来这一次是想简单介绍一下Boost里面的协程库的使用的,但是Boost.Coroutine已经被废弃了,而Boost.Coroutine2目前 ...

  7. C&plus;&plus;17尝鲜

    https://cloud.tencent.com/developer/article/1351910 [译]C++17,optional, any, 和 variant 的更多细节 用户261520 ...

  8. Golang源码探索&lpar;二&rpar; 协程的实现原理

    Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱, 虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻 ...

  9. Golang源码探索&lpar;二&rpar; 协程的实现原理(转)

    Golang最大的特色可以说是协程(goroutine)了, 协程让本来很复杂的异步编程变得简单, 让程序员不再需要面对回调地狱,虽然现在引入了协程的语言越来越多, 但go中的协程仍然是实现的是最彻底 ...

随机推荐

  1. HTML页面meta标签内容详解

    所有的浏览器都支持meta标签,用于提供页面相关信息,信息都是以名(http-equiv和name标示)/值(content标示)对的形式现实. 属性content,用于定义http-equiv(定义 ...

  2. 【SharePoint学习笔记】第2章 SharePoint Windows PowerShell 指南

    快速了解Windows PowerShell     从SharePoint 2010开始支持PowerShell,仍支持stsadm.exe工具:     可以调用.NET对象.COM对象.exe文 ...

  3. Android res&sol;raw vs assets

    common: 1.两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制. difference: 1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源I ...

  4. USACO 2&period;4 Cow Tours

    Cow Tours Farmer John has a number of pastures on his farm. Cow paths connect some pastures with cer ...

  5. 蓝桥网试题 java 基础练习 矩阵乘法

    ------------------------------------------------------------ 第一次感觉到好好学习的重要性QAQ 在做这道题之前请先学会 :矩阵乘法(百度百 ...

  6. 【ASP&period;NET MVC 学习笔记】- 13 Child Action

    本文参考:http://www.cnblogs.com/willick/p/3410855.html 1.Child action 和 Patial view 类似,也是在应用程序的不同地方可以重复利 ...

  7. Poj3683:Priest John&&num;39&semi;s Busiest Day

    题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然 ...

  8. Spark架构原理

  9. RobotFrameWork编写接口测试及如何断言

    1. 前言 本篇是第一系列(Http接口自动化)的第五课程,如果对系列课程大纲不清楚的,可以查看<RobotFramework系列免费课程-开课了~>. 前面我们介绍了,在真正实施前,需先 ...

  10. 剑指Offer 22&period; 从上往下打印二叉树 (二叉树)

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 题目地址 https://www.nowcoder.com/practice/7fe2212963db4790b57431d9ed25 ...