The current Boost 1.55 implementation offers two kinds of unidirectional coroutines. One is a pull-type, which is a coroutine that takes no parameters and returns a value to the main context; the other is the push-type, which is a coroutine that accepts a parameter from the main context but returns no value.
How can I combine these two to create a bidirectional coroutine that both accepts a parameter and returns a value? On the surface it seems like it should be possible, but I can't quite figure out how to do it with the building blocks I have in boost::coroutine
. There used to be a bidirectional coroutine in older Boosts, but it is now deprecated and undocumented, so I shouldn't rely on it.
ie, I would like something analogous to this:
void accumulate( pull_func &in, push_func &out )
{
int x = 0;
while ( in )
{
x += in.get() ; // transfers control from main context
out(x); // yields control to main context
}
}
void caller( int n )
{
bidirectional_coro( accumulate );
for ( int i = 0 ; i < n ; ++i )
{
int y = accumulate(i);
printf( "%d ", y ); // "0 1 3 6 10" etc
}
}
These types are provided by boost::coroutines::coroutine, which is a template that is instantiated with void in Example 51.1. To use coroutines, you need pull_type and push_type.
To use cooperative () as a coroutine, the types pull_type and push_type are used. These types are provided by boost::coroutines::coroutine, which is a template that is instantiated with void in Example 51.1. To use coroutines, you need pull_type and push_type.
To use coroutines, you need pull_type and push_type. One of these types will be used to create an object that will be initialized with the function you want to use as a coroutine.
With Boost.Coroutine it is possible to use coroutines in C++. Coroutines are a feature of other programming languages, which often use the keyword yield for coroutines. In these programming languages, yield can be used like return.
Actually, boost coroutine was bidirectional when it was first included in boost(1.53 I think).
http://www.boost.org/doc/libs/1_53_0_beta1/libs/coroutine/doc/html/coroutine/coroutine.htm
That code should still be compatible with the most recent version of boost, with minor modification if anything.
Also, you could use boost::context directly to create your own coroutine class.
http://www.boost.org/doc/libs/1_55_0/libs/context/doc/html/index.html
The parameter 'intptr_t vp' of fcontext_swap can be use to pass values/pointers back and forth, or you could store values in the coroutine itself, as member variables of your coroutine class should be valid from both contexts.
edit:
The short answer to your original question is no. What you are asking cannot be done. Each coroutine has it's own stack and context, which are not accessible from other coroutine instances. Also, when you jump into the coroutine's context, the state of the calling context is stored in that coroutine instance, and a jump back to the original context can only be made by calling into the argument that that coroutine passed into your function.
But, variables declared outside the local scope of the coroutine will be valid from inside and outside the coroutine function. So you could use a coroutine::push_type, and push a pointer instead of a value. You could use the value, and then modify it before jumping back to the original context.
Also, you can safely pass pointers to local variables into the coroutine, since they won't be destroyed until you jump back out of the coroutine and run the calling scope to completion.
you could look at the example contained in boost.coroutine https://github.com/boostorg/coroutine/blob/master/example/cpp03/chaining.cpp
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With