1 介绍

    协程分为对称协程(symmetric)和非对称协程(asymmetric),对称协程需要显式指定将控制权yeild给谁,非对称协程可以隐式的转移控制权给它的调用者,boost coroutine2实现的是非对称协程.
    Boost库中的协程支持两种方式:

           一种是封装了Boost.Coroutine的spawn,是一个stackful类型的协程;

           一种是asio作者写出的stackless协程。
 

     Boost.Asio中的stackless协程是由coroutine类和一些宏来实现的。coroutine类非常简单,包括四个函数,一个int类型变量,用来保存当前函数的运行状态,与之配合使用的宏中,因采用switch来实现,所以可以根据这个整型变量的值实现跳转。

2 伪关键字

Boost.Asio定义了一些宏,构成所谓的“伪关键字”

2.1 reenter

reenter用来定义协程内容,用法如下:

reenter (coroutine变量)   

{

  ... coroutine body ...

}

     第N次执行reenter代码块时,对应执行reenter代码块中第N个yield/fock

     上面代码块如在成员函数内,coroutine变量用this,否则是变量名,最好别在body中定义变量,否则有麻烦(reenter的实现是用switch来做的)。

2.2 yield

yield的用法大致如下:

yield … 或 yield {  …  }

2.3 yield return

yield后加return,则reenter块后的代码不执行了。

2.4 yield;

本次进入reenter块什么都不做,但计数会增加

2.5 yield break

终止,再也不会进入reenter块

2.6 fork

    fork用于“复制”协程,类似于unix的fork,程序先执行fork的代码,完毕后,再接着运行fork下一行代码

 

3 例子

3.1 例子1

#include <boost/asio/yield.hpp>
#include <boost/asio/coroutine.hpp>
#include <iostream>

boost::asio::coroutine c;

void foo(int i)
{
    reenter(c)
    {
        yield std::cout<<"foo1 "<<i<<std::endl;
        fork foo(100);
        yield std::cout<<"foo2 "<< i+1<<std::endl;
    }
}
int main()
{
    foo(1);
    foo(2);
    foo(3);
    return 0;
}

这个程序的输出是。。。

foo1 1
foo2 101
foo2 3

这个咋看之下有点难以理解,我们先忽略具体的细节,解释一下这是怎么回事。

首先,我们需要声明一个corountine,然后将需要重复进入的代码用reenter包括起来。第一次调用foo的时候,代码执行到第一个yield,此时,foo直接返回。

第二次调用的时候,程序直接执行上一次yield之后的代码,即fork,此时,程序调用foo,需要注意的是,被调用的fork不再执行第一个yield,而是直接从当前语句开始执行,于是得到输出foo2 101,返回之后,程序调用fork之后的yield,得到输出foo2 3

第三次调用的时候,由于不再有任何未执行的yield,因此不再产生任何输出。

从结果中可以看出:

    第N次执行reenter代码块时,对应执行reenter代码块中第N个yield/fock

 

3.2 例子2:

boost::asio::coroutine c;    
boost::asio::coroutine c2;    
void forkit(int i)
{
    reenter(c2) 
    {
        yield std::cout<<"forkit1 "<< i<<std::endl;        
        yield std::cout<<"forkit2 "<< i<<std::endl;                    
    }        
}
 void foo(int i)
{
    reenter(c) 
    {
        yield 
        {
            std::cout<<"foo1 "<<i<<std::endl;
            return;
        }
        fork foo(10);
        yield std::cout<<"foo2 "<< i<<std::endl;
        fork forkit(100);        
        yield std::cout<<"foo3 "<< i<<std::endl;
        yield break;
        yield std::cout<<"foo4 "<< i<<std::endl;            
    }
    printf("=====\n");
}
int main()
{
    forkit(1);
    
    foo(1);
    foo(2);
    foo(3);    
    foo(4);    
    foo(5);            
    return 0;
}
 
输出:
forkit1 1
foo1 1
foo2 10
=====
foo2 2
=====
forkit2 100
foo3 3
=====
=====
=====

程序运行示意图
boost yield fock介绍

 

参考:

https://blog.csdn.net/guxch/article/details/82804067

https://toutiao.io/posts/d2eeed/preview

相关文章: