On 24 June 2015 at 11:48, Giovanni Piero Deretta
On 24 Jun 2015 10:11 am, "Niall Douglas"
wrote: On 24 Jun 2015 at 1:09, Vicente J. Botet Escriba wrote:
Sean Parent suggests (See [1] Better Code: Concurrency) to remove the promise and left the packaged_task serve as single provider of a
future.
Both are created at once using the package factory.
I was at his talk at C++ Now.
The first thing which put me off his proposal was that he appears to be unaware of the highly optimised and very flexible de facto task concurrency system in C++ which has been around for years, and has just recently been standardised. It's called ASIO.
I also think packaged_task is overkill for creating futures. There are some times you really do just want a promise and nothing more.
There is no reason for a packaged task implementation to be more heavy weight than a promise. If the packaged task is [](T x) { return x; } then it is also semantically equivalent to promise<T>, just in a nicer interface. Bonus points it works beautifully with ASIO without any explicit support from ASIO itself.
I think this is a very important point. Of course the interaction is better with most existing code bases of which ASIO is merely one (important) example. It is clear that in at least some cases the packaged task implementation need not add overhead. Does anyone have any examples where one needs the additional abstraction for optimal performance?
There are even times you just want to create a future standalone, and for that we now have make_ready_future().
His future library doesn't include a shared_future as the future contains a value that can be observed several times.
If I remember rightly, internally his future has a shared_ptr, which really means he's proposing that future becomes a shared_future. I had doubts before until that part, but that killed his proposal for me. It's a non-starter as a practical design for my needs, but is still useful for ideas.
His implementation uses a shared ptr, but I think you could do without by deep copying the futures and internally chaining via then. This way you only pay the cost if you actually copy.
Is there any data about this trade-off? It seems that requiring a deep copy could, at least under some use-cases be substantial overhead. With a deep copy requirement are you prohibiting a wrapper that uses a shared_ptr? It seems more idiomatic to default to value-type semantics while providing flexibility to reduce copy/clone overhead.
I strongly believe that 'then' and other accessors should be non const so that concurrent calls *on the same future* need not be supported.
Is this a necessary logical result of the const-ness, or do you mean you desire the absence of const to be able to assert misuse? I'm wondering if we can define a desing contract such that some futures may be called multiple times while for others this is not allowed. This doesn't seem like it ought to be part of the future interface, but more a contract of the abstractions being operated upon by the future. Perhaps I'm not understanding a use-case?
-- gpd
Neil