Boost Corutine
cpp
#include <boost/coroutine/asymmetric_coroutine.hpp>
#include <iostream>
using boost::coroutines::coroutine;
using std::cout, std::endl;
void counter(int x, coroutine<int>::push_type *yield = nullptr) {
for (int i = 0; i < x; ++i) {
if (yield) (*yield)(i * 10);
}
}
int main() {
auto coro = coroutine<int>::pull_type([](coroutine<int>::push_type &x) {
counter(15, &x);
});// 1) print 0 in counter
int v;
auto it = begin(coro);
cout << "do something" << endl;// 2) do something
v = *it;
++it;// 3) print 1 in counter
cout << v << endl;// 4) 0
cout << "do something else" << endl;// 5) do something else
v = *it;
++it;// 6) print 2 in counter
cout << v << endl;// 7) 10
}
Boost Coroutine2
Some differences:
- Boost.Coroutine2 requires C++11
- Boost.Coroutine provides symmetric and asymmetric coroutines, Boost.Coroutine2 only provides asymmetric coroutines.
cpp
// g++ boco2.cpp -std=c++17 -lboost_coroutine -lboost_context
#include <boost/coroutine2/coroutine.hpp>
#include <iostream>
using coro_t = boost::coroutines2::coroutine<int>;
int main() {
coro_t::pull_type source([&](coro_t::push_type& sink) {
int first = 1, second = 1;
sink(first);
sink(second);
for (int i = 0; i < 8; ++i) {
int third = first + second;
first = second;
second = third;
sink(third);
}
});
for (auto i : source) std::cout << i << " ";
}
symmetric vs asymmetric coroutines
Symmetric coroutines can be used to implement user-land threads (a symmetric coroutine represents a userland thread; the scheduler jumps from one coroutine to the next symmetric coroutine, e.g. the next user-land thread is scheduled) more efficiently than asymmetric coroutines. This is obvious because symmetric coroutines do not need to jump back to the caller in order to resume the next user-land thread.
Asymmetric coroutines need more context switches than symmetric coroutines in order to achive the same functionality.