Boost logo

Boost :

Subject: Re: [boost] Common future base class (was Re: Boost.Fibermini-review September 4-13)
From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2015-09-06 17:26:29


On Sun, Sep 6, 2015 at 7:22 PM, Agustín K-ballo Bergé
<kaballo86_at_[hidden]> wrote:
> On 9/6/2015 1:35 PM, Peter Dimov wrote:
>>
>> Hartmut Kaiser wrote:
>>
>>> template <typename Future...>
>>> requires(is_future<Future>)...
>>> future<tuple<Future...>> when_all(Future &&... f)
>>> {
>>> (await f)...;
>>> return make_tuple(std::forward<Future>(f)...);
>>> }
>>
>>
>> I've always found when_any much more interesting than when_all. Is it as
>> trivial to implement with await as when_all?
>>
>
> The await proposal already deals with heterogeneous futures (awaitable
> types). It comes with traits and customization points on top of which it is
> built. Using `await_suspend` one can attach a callback to an awaitable
> object that fires when the future becomes ready (without consuming it).
> An
> heterogeneous `when_all` would be built on top of `await_suspend`, plain
> `await` is optimal when one just want the semantic of `when_all`. Similarly,
> an heterogeneous `when_any` would use `await_suspend` to attach a callback
> to all awaitable objects, and the first callback to run would make the
> resulting future ready (potentially but not necessarily canceling all other
> callbacks).
>

In the last coroutine proposal (is it N4499). It seems that
await_suspend(h) is guaranteed to work only if 'h' is of type
coroutine_handle<P>. Also, at least from the example implementation in
N4286, await_suspend is not really more powerful than 'then'.

In fact the previous when_all implementation and the when_any you've
described can be implemented on top of 'then'.

The problematic scenario is performing wait_any multiple times on the
same future set as the attached continuations will continue growing
every time.

BTW, it is sort of possible (but quite inefficient) to attach a
continuation to an unique future without consuming it:

template<class T>
future<void> when_ready(std::future<T>& x)
{
   auto shared_x = x.share();
   x = shared_x.then([](auto&&x) { return x.get(); }
   return x.then([](auto&&) {});
}

future<T> x = ...;

await when_ready(x);
// or
when_ready(x).then([] { /* do something */ });

-- gpd


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