协程介绍和boost中的协程实现——Boost.Coroutine2

定义

协程是一个无优先级的子程序调度组件,允许子程序在特定的地方挂起和恢复。

协程分类

协程分为对称协程(symmetric)和非对称协程(asymmetric),对称协程是指所有协程都是对等的,需要显式指定将控制权yeild给谁;非对称协程是指协程记录调用者,可以隐式的转移控制权给它的调用者。

协议、线程和进程关系

线程处于进程之中,协程处于线程之中,线程有系统内核调度,而协程有程序员自己调度。一个线程可以有多个协程,而且只要内存足够,一个线程中可以有任意多个协程;但某一时刻只能有一个协程在运行,多个协程分享该线程分配到的计算机资源。协程是追求极限性能和优美的代码结构的产物。

协程的特点

  1. 同其他数据类型一样,协程也是第一类(first-class)对象,可以被当参数传递等操作;
  2. 运行特点是挂起运行,离开协程,过后再进入,恢复运行;
  3. 具有对称和非对称的转移控制机制;
  4. 挂起前和恢复后本地变量的值是一致的;
  5. 有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;

}

 

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值