boost::coroutines2中的push_type和pull_type的使用

具体的协程的基本使用可以参考:
Boost中的协程—Boost.Coroutine2(这篇博文很详细,唯一美中不足的是有处笔误,在本文最后指出,并做了更正)

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

我记录一下上面博文中忽略的一个很重要,也容易混淆的一点,这个会影响我们正常使用boost::coroutines2。

我们先看看两个类似的例子:

例子一:

#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 ";

	std::cout << std::endl;
	if (!source)
	{
		std::cout << "soure is not valid" << std::endl;
	}

	getchar();
	return 0;
}

运行结果:

a=1 b=2 c=3
soure is not valid

例子二:

#include <iostream>
#include <typeinfo>
#include "boost/coroutine2/all.hpp"

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=";
	source();

	std::cout << std::endl;
	if (!source)
	{
		std::cout << "soure is not valid" << std::endl;
	} 

	getchar();
	return 0;
}

运行结果:

1=a 2=b 3=c
soure is not valid

看到这两个类似的程序,结果却不同,困惑就产生了。我们来查资料解决困惑。
Class coroutine<>::pull_type

template< typename Fn > pull_type( Fn && fn)

Effects:
Creates a coroutine which will execute fn, and enters it.

创建一个将来会执行Fn的coroutine,并且进入该Fn。意思是说,pull_type类型的,在构造完成后,就会调用一次Fn。

我们再来看看Class coroutine<>::push_type

template< typename Fn > push_type( Fn && fn)

Effects:
Creates a coroutine which will execute fn.

差别就出现了。push_type只是创建一个将来会执行fn的coroutine,但是创建好后,并不马上执行这个fn。

接下来我们看看if (!source)是怎么回事。以pull_type为例(push_type也是类似的)

#include <boost/coroutine2/coroutine.hpp>

template< typename R >
class coroutine<>::pull_type
{
public:
    template< typename Fn >
    pull_type( Fn && fn);

    template< typename StackAllocator, typename Fn >
    pull_type( StackAllocator stack_alloc, Fn && fn);

    pull_type( pull_type const& other)=delete;

    pull_type & operator=( pull_type const& other)=delete;

    ~pull_type();

    pull_type( pull_type && other) noexcept;

    pull_type & operator=( pull_type && other) noexcept;

    pull_coroutine & operator()();

    explicit operator bool() const noexcept;

    bool operator!() const noexcept;

    R get() noexcept;
};

template< typename R >
range_iterator< pull_type< R > >::type begin( pull_type< R > &);

template< typename R >
range_iterator< pull_type< R > >::type end( pull_type< R > &);

我们发现它重载了布尔运算符

    explicit operator bool() const noexcept;
    bool operator!() const noexcept;

也就是说我们可以通过判断它的bool值,来判断它是否有效。当它无效的时候,我们就不能再调用它去执行Fn了。
我们来看看它的实现:

template< typename T >
pull_coroutine< T >::operator bool() const noexcept {
    return nullptr != cb_ && cb_->valid();
}

template< typename T >
bool
pull_coroutine< T >::operator!() const noexcept {
    return nullptr == cb_ || ! cb_->valid();
}

很简洁,先判断回调cb是否为nullptr,如果不为nullptr,再检查cb是否有效。

参考:
协程介绍和boos中的协程实现——Boost.Coroutine2

Boost中的协程—Boost.Coroutine2
这篇博文也写得不错,就是可能说出现了一处笔误:

coroutine<>::pull_type在构造函数时,调用了一次协程函数(注意示例1的输出),而coroutine<>::pull_type没有。

应该是:
coroutine<>::pull_type在构造函数时,调用了一次协程函数(注意示例1的输出),而coroutine<>::push_type却不会马上执行一次协程函数。
(个人的体会,也通过官网的资料和源码证实了)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值