On 24 Jun 2015 at 16:30, Neil Groves wrote:
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?
Yes: https://boostgsoc13.github.io/boost.afio/doc/html/afio/reference/class es/enqueued_task_r___.html std::packaged_task has a very unhelpful design for real world programming. The ability to extract its its internally held promise, and optionally set it early within the task is exactly what afio::enqueued_task does. If I remember rightly, I added a good 30% to performance using this slightly enhanced packaged_task. For real world sized tasks this stuff matters.
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.
This is effectively the same as a linked list, and that is terrible for performance after a certain depth of chains. You're better off allocating memory and using shared_ptr after a certain depth.
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?
future<T> returns a one-shot value. Therefore its .then() is also one-shot because it equals consuming any future value. This makes total sense. shared_future<T> returns its value as often as desired. In that circumstance it is implied that more than one thread could fetch a value. It therefore needs to be thread safe. AFIO uses a lot of shared_future<T> currently, and it's all done under the assumption that it's thread safe. I'd assume so does any other code using shared_future<T>. I think the ship has sailed on that design choice. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/