Boost logo

Boost :

From: Stjepan Rajko (stipe_at_[hidden])
Date: 2007-05-02 23:06:10


Hi Braddock,

I got futures to work very nicely both in handling return values, and
to handle "in/out" arguments. Assigning the return value to a
non-future variable (or passing a reference instead of a future for an
"in/out" argument) makes the call behave synchronously.

I really like this approach and I think I will start taking out the
old sync code that now seems to be unnecessary. This also goes along
well with what Jeff was suggesting - the rpc framework will be
fundamentally asynchronous with the user having to overtly (but very
easily) make it behave in a synchronous manner if that's what is
desired.

More notes below:

On 5/2/07, Braddock Gaskill <braddock_at_[hidden]> wrote:
>
> When future<T>::cancel() is called, a future_cancel exception is set in the
> <snip>

This explanation helps - thanks.

> Now, if you have both a return value future, and a set of OutArg futures, you
> can handle that in one of two ways:
> <snip>

Cool - this makes a lot of options possible:
a) cancelling an individual future cancels the whole call and all
associated promises
b) cancelling an individual future only cancels the need for that
argument / return value (a possibly nice but complicated way to follow
up on this would be to notify the server that the argument is no
longer necessary and to not marshal it back). To cancel the whole
call, the user must call a member function of the call handler.

I think I prefer option 2, especially if a nifty little call handler
is returned by the call like you suggested.

>
> Yeah, I'm sure you'll want a bit more power and probably a few optional
> parameters in your 'rpc()' call. Maybe:
>
> future<T> rpc(RpcParameterSet, F func, ARG1, ..., ARGN)
>
> You may also want to not return a future directly, but perhaps return some
> rpc_call_handle type which is implicitly convertable to a future.
>
> rpc_call_handle<T> rpc(...)
>

I already have a call handler (the actual underlying syntax I use is
something like rpc(call(function_id, args...), options), but I like
the idea making the handler (either the same one I already use or some
version of it) implicitly convertible to a future and returned by the
call.

> > I do plan to add exception transportation. Is it possible to have the
> > future throw a custom (specified by the promise) exception? Your
> > point 3) suggests that this is possible also.
>
> Yes, within certain limits.
> Thank Peter Dimov for his exception_ptr handling.
> In fact, looking at my code now I think I could improve my implementation to
> allow throwing arbitrary exception types. This is one of those "early" areas.
>

Thanks, Peter.

And no problem about it being an early area, exception handling on my
end has not even reached the early stage. No rush.

> Work-around for the
> lack of default constructor would be:
>
> future<int> multiplied(promise<int>()); //will immediately be set to broken_promise, but that okay.
> (or ask me to provide a default constructor which does this, which is probably a good idea)

Having a default constructor like that would be great. I was able to
get an "out" parameter back through a future that was constructed from
an empty promise, and then reassigned inside the call, like you
suggested. The default constructor would make it simpler, and this
behavior seems to be appropriate for a default constructor in any
case.

> > Also, if the argument was "InOut" rather than just "Out", we'll need
>
> Well, if you use the pass-by-reference future solution above, then you COULD
> pass in an already-set future, and then have the rpc() call take that value and
> then assign the referenced future to a new promise. I'm not sure I like that
> though, it seems abusive and confusing.
>

I tried this method and it worked - but I also agree in that it
doesn't seem very elegant... I can see somewhat of a need for this in
a general setting, where two producer/consumers are shooting values
back and forth to each other. Rather than using two pairs of
promise/future objects, maybe a single two-way channel would be a
useful specific case to handle.

If not, I can always have the user pass a pair (in_value, out_future)
which seems OK.

> Yes, I need to write some real documentation. :)
>
> Please continue to ask me and I will provide support. I know the
> implementation will benefit from it. We can move to private e-mail if you
> prefer (braddock_at_[hidden]).

Thanks! I might move the more implementation-specific talk to the
e-mail, and things to do with design decisions/options/questions I'll
still post here so those interested can comment.

Stjepan


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