On 24 Jun 2015 8:08 am, "Vicente J. Botet Escriba"
Le 24/06/15 02:18, Giovanni Piero Deretta a écrit :
On Wed, Jun 24, 2015 at 12:09 AM, Vicente J. Botet Escriba
wrote:
which opens a lot of optimiation opportunities (for example if the future is non copyable non movable, no memory allocation is required).
Sean' future is copyable and movable. Do you mean if the stored value? Are thinking of the future<void>
specialization?
When no memory allocation will be needed?
The default future will allocate, but a non-movable non-copiable variant is conceivable that stores the shared state inline. You get a promise/packaged_task from it and pass it to the producer which need not to know.
His future library doesn't include a shared_future as the future
contains a
value that can be observed several times.
This is my biggest issue with Sean's design. Sharing the state among multiple consumes pretty much requires heavy weight synchronization.
Could you elaborate? It this different for std::shared_future?
I can chose not to use shared_future and use a plain future if I'm concerned about the shared count cost. Note that now I believe that this aspect of Sean design is implementable without cost if the future is never copied.
But see below.
The continuation takes the value and not the future. So a future can have several continuations.
What's the thread safety guarantees of future? 'As safe as int' or, for example, concurrent calls to .then are allowed? If the former, a copy could be a real deep copy (a new shared state is allocated and broadcasting is internally done via 'then'). That's not how Sean future is currently implemented though.
Of course, concurrent calls to .then must be allowed. I don't see when would you need the copy of the shared state.
If the store type is movable only, then the future can have only one continuation. Not really strange coming from Sean, future and packaged_task are
copyables
:) One more thing, there is not get no wait, but a get_try that return an optional<T>.
Intresting, so if a consumer needs wait must implement it on top of then. This is fine, but you need a way to unregister a 'then'.
I don't know. The std::experimental::future::then is the TS hasn't way to unregister a continuation. Why do you think it is needed now? It is because
Well you do not need to allow concurrent calls to then if you allow copying the future. Every thread can use its own copy of the future, although I see why Sean designed it this way: a future is a placeholder for the underlying type and pure reads are not racy for sane types. the future is shared?
Sean future doesn't have wait for example. If you want to implement timed waits on top of then you need a way to unregister a waiter. Similarly for wait_any. You can work around it of course. [...]
What are you missing ?
[...]
The when_any continuation probably needs to be passed the all the futures instead of just the value that is ready, so that it can be called recursively.
I would consider when_any as having associated a variant of the Ts as value type. The continuation should then be an overload of the alternatives. The continuation passed to all the futures could be an internal one that is called just once and cancelled just before the first call.
Could you elaborate the recursive part?
when_any also requires the ability to unregister a continuation from a future, otherwise if called 'in a loop' the number of continuations associated with futures will grow.
You are right that they will grow. I'm wondering if this is a real interface issue or a QOI.
Needs this use case a special consideration even if it could decrease the
Let say I have N futures. As soon as one them is ready I want to do something. I Call when_any with a continuation. After that I might want wait again for the remaining N-1 futures and maybe rearm the one that just got ready. If the continuation had access to all the futures then it would only need to call when_any again with itself as the continuation. This is equivalent to calling an hypothetical blocking wait_any in a loop. performances of more usual cases?
My use case is implementing a coroutine variant of wait_any efficiently on top of when_any. See: https://github.com/gpderetta/libtask/blob/master/tests/future_test.cpp (Look for wait_any)