概述
定义
协程是一个无优先级的子程序调度组件,允许子程序在特定的地方挂起和恢复。
协程分类
协程分为对称协程(symmetric)和非对称协程(asymmetric),对称协程是指所有协程都是对等的,需要显式指定将控制权yeild给谁;非对称协程是指协程记录调用者,可以隐式的转移控制权给它的调用者。
协议、线程和进程关系
线程处于进程之中,协程处于线程之中,线程有系统内核调度,而协程有程序员自己调度。一个线程可以有多个协程,而且只要内存足够,一个线程中可以有任意多个协程;但某一时刻只能有一个协程在运行,多个协程分享该线程分配到的计算机资源。协程是追求极限性能和优美的代码结构的产物。
协程的特点
- 同其他数据类型一样,协程也是第一类(first-class)对象,可以被当参数传递等操作;
- 运行特点是挂起运行,离开协程,过后再进入,恢复运行;
- 具有对称和非对称的转移控制机制;
- 挂起前和恢复后本地变量的值是一致的;
- 有stackless和stackful两种类型
使用
协程可以在两个子例程中轻松地切换运行,如果不使用协程就需要把两个子例程切分成很多个片段,代码会变得复杂。协程的大概流程如下图所示:
Boost提供了两个创建协程的类:pull_type和push_type,pull的意思是从主运行环境“拉”数据到协程环境,push的意思是从协程环境将数据“推”到主运行环境中,pull_type通过get()方法拉取数据,push_type通过 operator()推数据;即在协程中,pull_type.get()可以得到外部传入的数据,而push_type()可以将数据传递到外部环境。为此,pull_type提供了输入iterator及重载了std::begin()/std::end(),push_type提供了输出iterator及重载了std::begin()/std::end(),方便它们的循环调用。
例子1:交替运行
#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; } |
输出:
a=1 b=2 c=3
该示例以pull_type创建协程,以push_type作为协程函数的参数,两者之间没有传递数据,子例程和main例程交替切换运行。
例子2:协程环境传递数据给主环境
#include <iostream> #include <boost/coroutine2/all.hpp>
int main() { typedef boost::coroutines2::coroutine<int> coro_t2; coro_t2::pull_type source( [&](coro_t2::push_type& sink){ std::cout<< " coroutine 1" << std::endl; sink(1); // push {1} back to main-context std::cout<< " coroutine 2" << std::endl; sink(2); std::cout<< " coroutine 3" << std::endl; sink(3); });
while(source) { int ret=source.get(); // pushed sink() data std::cout<< "move to coroutine-function "<< ret << std::endl; source(); // context-switch to coroutine-function std::cout<< "back from coroutine-function "<< std::endl; } return 0; }
输出为: move to coroutine-function 1 coroutine 1 back from coroutine-function move to coroutine-function 2 coroutine 2 back from coroutine-function move to coroutine-function 3 coroutine 3 back from coroutine-function |
该示例以pull_type创建协程,以push_type作为协程函数的参数,由于主环境是pull,因此主环境可以通过get方法得到协程传出来的数据
例子3:主环境传递数据给协程环境
#include <iostream> #include <boost/coroutine2/all.hpp>
void foo(boost::coroutines2::coroutine<std::string>::pull_type & sink) { std::cout << "get " << sink.get() << "from main() n"; sink(); std::cout << "get " << sink.get() << "from main()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 << "to foo()n"; source(str1); std::cout << "pass " << str2 << " to foo()n"; source(str2); return 0; } |
例子4:协程迭代器使用
#include <iostream> #include <boost/coroutine2/all.hpp> #include <boost/coroutine2/detail/push_coroutine.hpp> #include <boost/coroutine2/detail/pull_coroutine.hpp>
// 方法一 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"; } } // 方法二 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 < 10; i++) { std::cout << "retrieve " << sink.get() << "n"; sink(); } }
int main(){ boost::coroutines2::coroutine<int>::push_type source(foo); for (int i = 0; i < 10; i++) { source(i); } return 0; } |
最后
以上就是魁梧睫毛膏为你收集整理的协程介绍和boost中的协程实现——Boost.Coroutine2定义协程分类协议、线程和进程关系使用的全部内容,希望文章能够帮你解决协程介绍和boost中的协程实现——Boost.Coroutine2定义协程分类协议、线程和进程关系使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复