介绍
本文主要介绍了怎么通过 boost::coroutine2 来在 C++ 代码中使用协程,详细的介绍请移步 boost::coroutine2 文档。
总体认识
一个协程可以认为是把代码分成了两个部分,而我们可以控制执行权在这两部分跳转,每次跳转同时也可以传递数据。boost::coroutine2 提供的是非对称协程(asymmetric coroutines),将代码分成的两个部分有调用和被调用者关系。
boost::coroutine2 提供的协程只能单向传递数据,数据只能单向的从一个代码块流向另一个代码块。流入流出分别对应着 push_type 和 pull_type 类型,由这两个类型组成协程间跳转的通道,同时也是数据传递的通道。
具体使用
include <boost/coroutine2/all.hpp>
- 从协程中获取数据
using coro_t = boost::coroutines2::coroutine<int>;
auto source = coro_t::pull_type([](coro_t::push_type & yield)
{
for (auto i = 0; i != 3; ++i)
{
yield(i);
}
});
for (auto value : source)
{
std::cout << value << std::endl;
}
输出:
0
1
2
- 向协程中放置数据
using coro_t = boost::coroutines2::coroutine<int>;
auto sink = coro_t::push_type([](coro_t::pull_type & acquire)
{
for (auto value : acquire)
{
std::cout << value << std::endl;
}
});
for (auto i = 0; i != 3; ++i)
{
sink(i);
}
输出:
0
1
2
说明
- push_type 和 pull_type 都有 operator bool,在返回 false(协程结束了) 时,不能在放入数据或者获取数据。
- pull_type 可以通过 begin() 获得迭代器,也可以通过调用 get 获取值,通过 operator() 来转换控制权。
- pull_type 应该先调用 get 在调用 operator()。
使用场景
无限长的列表(惰性求值)
using coro_t = boost::coroutines2::coroutine<int>;
auto source = coro_t::pull_type([](coro_t::push_type & yield)
{
auto count = 0;
while (true)
{
yield(++count);
}
});
while (true)
{
auto const value = source.get();
std::cout << value << ' ';
if (value == 10) { break; }
source();
}
输出:
1 2 3 4 5 6 7 8 9 10