Boost logo

Boost :

Subject: Re: [boost] [coroutine] interface suggestion
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-09-20 07:17:15


Le 20/09/12 12:18, Giovanni Piero Deretta a écrit :
> On Thu, Sep 20, 2012 at 3:51 AM, Vicente J. Botet Escriba <
> vicente.botet_at_[hidden]> wrote:
>
>> Le 19/09/12 21:05, Oliver Kowalke a écrit :
>>
>> int f( caller_t & c, strg & s, int x) {
>>> caller_t::yield_t b = c.bind( s, x); // s and x are now used to
>>> store the next calls.
>>> b.yield( 7); // alternative b( 7)
>>> // here s and x have been reassigned
>>> }
>>>
>>> c.bind() retrieves the addresses of the parameters used to store the
>>> values (for each entering of f).
>>> only yield_t will provide yield() function.
>>>
>>> what do you think?
>>>
>>>
>>> This is exactly what I proposed above :) and for the time been this is
>> the best interface I have found.
>
> I have issues with this interface, though:
> - Why do you need to explicitly bind? If you are required to bind the
> arguments of the coroutine-fn anyway, the trampoline might as well do it
> for you.
I don't need to if the library hides the bind.
> - As you described, you need to provide an alternate interface (i.e. get())
> to access the arguments from a nested function anyway. You might as well
> make this the only interface.
Yes.
> - Tying the caller_t to an object in the coroutine stack (the parameters),
> makes it very hard to move the caller object to another coroutine. This is
> important to implement pipelines, where yield does not return to the caller
> but the next coroutine in the pipeline.
You are surely right. I have not considered yet symmetric coroutine. Let
me think a little bit more about how this interact.
> - Also see below:
>
>
>> Note that as I commented in some of my first post related to bind, you
>> must take care of const and reference parameters in some tricky ways, as
>> in order to be able to reassign them you should do some casts. I hope this
>> will not cache some undefined behavior.
>>
> How would you exactly rebind references? I can't see any sane way to do
> it. I would expect the following code to work:
>
> int i = 0, j = 0;
> coroutine<void(int&)> coro([&](caller_t& caller, int& x) {
> caller.bind(x);
> assert(&x == &i); // ok
> caller.yield();
> assert(&x == &y); // ?????
> });
>
> coro(i);
> coro(j);

Yes, references could not be rebound. We could rebind types, pointers
but not references.
I guess the coroutine library could store a pointer on the caller
object, and allow to obtain them using get<>. But in this case the
coroutine function could not follow the coroutine signature.

int i = 0, j = 0;
coroutine<void(int&)> coro([&](caller_t& caller) {
               int& x = caller.get<0>;
                assert(&caller.get<0> == &i); // ok
                caller.yield();
                assert(&caller.get<0> == &j); //ok
});

coro(i);
coro(j);

Best,
Vicente

> tl;dr: have get() as the only way to access parameters and have the
> parameters themselves local variables (i.e. stack allocated) of the calling
> context, not of the callee.
>
I think you are right.

Best,
Vicente


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk