Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2008-06-02 11:07:50


Johan Torp:

> I often have some kind of top flow control mechanism for some threads
> which
> waits - without any time limit/poll - when there is nothing to do. It
> might
> be;
> - A message pump
> - An asio::io_service (calling run)
> - A job queue
> - A logical clock in reactive programming
>
> Within this thread code is executed while processing a message, servicing
> some thing, executing a job or inside a logical clock tick/instant. Let's
> call this X's client code. Inside the client code I imagine you often will
> create a new pending request to some service and get a future back to wait
> on. Instead of waiting directly on the future and stall the entire thread,
> you'd typically want to get a notification from X at a later point. Let's
> call this future F and let's for simplicity assume there is only one of
> it.
>
> This gives us the need to wait for either something to do in X or F.

The fundamental question is whether the layer you're calling should expose

    future<X> async_do_something( Y y );

or

    void async_do_something( Y y, function<void(X)> done );

Obviously, in a message-passing-based architecture, the second interface
would be more convenient as it allows you to just post an appropriate
message in 'done'.

The "completion callback" approach tries to express the second interface in
terms of the first, but I'm not quite sure that this is correct. Expressing
the first in terms of the second seems more natural to me.

future<X> async_do_something( Y y )
{
    promise<X> px;
    future<X> fx = px.get_future();
    async_do_something( y, bind( &promise<X>::set_value, move(px), _1 ) );
    return fx;
}

There's the small problem with the exceptions though.

void async_do_something( Y y,
    function<void(X)> done, function<void(exception_ptr)> failed );

future<X> async_do_something( Y y )
{
    shared_ptr< promise<X> > px( new promise<X> );
    future<X> fx = px->get_future();

    async_do_something( y,
        bind( &promise<X>::set_value, px, _1 )
        bind( &promise<X>::set_exception, px, _1 )
    );

    return fx;
}

which only reaffirms my experience that each time you see something
move-only, you are going to need shared_ptr to get around its limitations.
But that's another story. :-)


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