#define USE_CORO_VERSION 1 // yields to caller when 1,
// yields to parent when 2 (and crashes after parent exit)
#if USE_CORO_VERSION == 1
#include <boost/coroutine/all.hpp>
using coroutine = boost::coroutines::coroutine<void>;
#else
#include <boost/coroutine2/all.hpp>
#include <boost/system/config.hpp> // auto-link with Boost.System on Windows
using coroutine = boost::coroutines2::coroutine<void>;
#endif
#include <iostream>
#include <boost/lockfree/queue.hpp>
boost::lockfree::queue<coroutine::pull_type *> coroutine_queue(1024);
void start_child_coroutine();
void start_parent_coroutine(int params)
{
// workaround for boost::coroutines2::coroutine<void>::pull_type
// not having default constructor
coroutine::pull_type default_coroutine = coroutine::pull_type(std::move(default_coroutine));
coroutine::pull_type * pull =
new coroutine::pull_type(std::move(default_coroutine));
*pull = coroutine::pull_type
(
[=](coroutine::push_type & yield)
{
for (int i = 1; i <= 10; ++i)
{
// if we are in the middle (5th iteration out of 10)
// of parent coroutine - start child coroutine
if (i == 5 && params == 1)
{
start_child_coroutine();
}
coroutine_queue.push(pull);
yield();
std::cout << params;
}
std::cout << " leaving coroutine " << params << std::endl;
}
);
}
void start_child_coroutine()
{
start_parent_coroutine(2);
}
int main()
{
start_parent_coroutine(1);
for (;;)
{
coroutine::pull_type * c = nullptr;
bool got_coroutine = coroutine_queue.pop(c);
if (got_coroutine)
{
std::cout << "g";
(*c)();
if (!*c) delete c;
}
else
{
break;
}
}
}