前言
线程处于进程之中,协程处于线程之中,线程有系统内核调度,而协程有程序员自己调度。一个线程可以有多个协程,而且只要内存足够,一个线程中可以有任意多个协程;但某一时刻只能有一个协程在运行,多个协程分享该线程分配到的计算机资源。协程是追求极限性能和优美的代码结构的产物。
使用过程中需要包含#include <boost/coroutine2/all.hpp>,链接动态库:-lboost_coroutine -lboost_context。关于使用boost库错误,请看下图:
原理
boost提供的boost::coroutines2::coroutine<>::pull_type和boost::coroutines2::coroutine<>::push_type两个模板类配合实现协程功能,模板参数适用于两者传递值的类型。两个类都实现了operator()运算符重载,用于调用协程功能。
push_type::operator()用于将调用位置以下的代码直到下一个push_type::operator()为止,推送到协程队列中挂起。等待关联的协程pull()拉取。如果没有被拉取,被push的代码段将不会被执行。
pull_type::operator()用于将协程队列中被push()的代码段拉取到调用pull_type::operator()处执行,如果协程队列中没有被push()的代码,程序将会异常段错误,返回值139。调用pull时确保协程环境中有被push的代码段。
通信传值:协程环境中只能push想pull环境中传值,pull想push中传只能通过全局变量。
1 在创建协程对象时使用要传递的参数进行实例化模板对象如:boost::coroutines2::coroutine<int>::push_type& push,boost::coroutines2::coroutine<int>::pull_type pull(foo) 实例化模板类型要统一
2 值推送,在协程函数foo中通过push对象进行推送,如push(1)。
3 值获取,获取协程中推送的值,通过pull_type.get() 获取,获取当前push(xx) 的值:xx
4 获取的值是push()推送代码段队列中的首个值,不会因get()多次而进行下一个,只会获取当前的,直到协程环境执行到下一个push(xx),回到主环境中执行pull.get()才会get()到下个值。
示例
#include <boost/coroutine2/all.hpp>
#include <iostream>
// pull 和 push 只要有一个导致程序结束,另一个将不会被执行。 所以要保证 push和pull调用次数相等
// pull () 在构造时,将直接进入foo函数,直到遇到函数中的push(),回到主函数中。在主函数中直到遇到pull() 将再次回到foo函数中调用push位置,push()返回,继续向下执行,直到遇到下一个push().
void foo(boost::coroutines2::coroutine<int>::push_type& push)
{
std::cout << "into foo function" << std::endl;
push(1);
std::cout << "a = ";
push(2);
std::cout << "b = ";
push(3);
std::cout << "push done." << std::endl;
}
int main()
{
boost::coroutines2::coroutine<int>::pull_type pull(foo);
std::cout << "pull get value = " << pull.get() << std::endl;
pull();
std::cout << "pull get value = " << pull.get() << std::endl;
pull();
std::cout << "pull get value = " << pull.get() << std::endl;
pull();
std::cout << "pull done." << std::endl;
return 0;
}
输出
参考
Boost中的协程—Boost.Coroutine2
协程介绍和boost中的协程实现——Boost.Coroutine2