boost::coroutine2(stackful协程库)
来源:互联网 发布:app停车软件下载 编辑:程序博客网 时间:2024/05/22 08:33
协程可以很轻量的在子例程中进行切换,它由程序员进行子例程的调度(即切换)而不像线程那样需要内核参与,同时也省去了内核线程切换的开销,因为一个协程切换保留的就是函数调用栈和当前指令的寄存器,而线程切换需要陷入内核态,改变线程对象状态。
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 0;}如果把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 0;}模板参数为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 0;}
不难看出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 = 10;// 方法一:中规中矩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 = 0; i < N; i++) { std::cout << "retrieve " << sink.get() << "\n"; sink(); }}int main(){ boost::coroutines2::coroutine<int>::push_type source(foo2); for (int i = 0; i < N; i++) { source(i); } return 0;}
阅读全文
0 0
- boost::coroutine2(stackful协程库)
- c++协程5(boost::coroutine2)
- 引领Boost(二)(Boost::Any)
- 引领Boost(三)(Boost::tuple)
- 引领Boost(四)(Boost::smart_ptr)
- 引领Boost(五)(Boost::array)
- 引领boost(六)(boost::bind)
- 引领Boost(二)(Boost::Any)
- 引领Boost(三)(Boost::tuple)
- 引领Boost(四)(Boost::smart_ptr)
- 引领Boost(五)(Boost::array)
- 引领boost(六)(boost::bind)
- 学习boost(一)
- Boost.Asio(二)
- BOOST学习(一)
- Boost学习(二)
- 引领boost(开篇)
- Boost笔记(备查)
- PAT (Basic Level) Practise (中文)1045. 快速排序(25)
- QML与C++混合编程
- Ubuntu16.04+Nvidia GTX 1080+CUDA9.0+cuDNN7+Tensorflow1.4+Anaconda安装
- 从零学Java——异常处理机制
- OFFBOARD
- boost::coroutine2(stackful协程库)
- 数据结构-树的实现C++
- Java——SAX解析XML文件
- Android 二维码生成 带logo
- set&&map
- eclipse中 使用JPA Tools 根据数据库表自动生成实体类
- UR机器人TCP编程实践
- Java面向对象基本语法
- HttpClient 教程