Domanda

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
   }
}
È stato utile?

Soluzione

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.

Altri suggerimenti

you could look at the example contained in boost.coroutine https://github.com/boostorg/coroutine/blob/master/example/cpp03/chaining.cpp

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top