Le 24/06/15 11:13, Niall Douglas a écrit :
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. Why do you mix any discussion about futures with 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. You could have a packaged_task that just acts as a promise. The single difference is the interface. There are even times you just want to create a future standalone, and for that we now have make_ready_future(). Agree for make_ready_future/make_exceptional_future. This is not incompatible with Sean design.
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. std::future has always some kind of shared_ptr to the shared state. The share nature on shared_future is related to the fact that the value can be read several times. 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. Why? because it uses heap memory?
Scales better. IIUC the implementation allows to implement when_all on top of future/packaged_task. The trick is that that the packaged_task can store some context.
async has always an Scheduler as parameter. Scheculers are just Copyable Callables having this signature void(void()). There is no need for function add/spawn.
when_all has also a callable as argument.
I find the Sean's design clean and simple (See the code [2]). What do you think of it? Do you see any issues on it? I think it's very easy to do a beautiful design that trades off performance for a beautiful design. Where do you see there are performances issues that can not be fixed without changing the interface, that is that are not QOI. I also think you can design a system which has poor low wait object performance but excellent high wait object performance, and vice versa. The problem to be solved is what balance between the two is best for most users of your design. Where do you place the std::future design, the Sean's design and why not your design respecto the the previos clasification?
In the future-promise I am currently building, I always ask this question when thinking about a potential feature or design:
"Will this future-promise be lightweight enough to promise on every single SHA256 round in a hash?"
That's about 400-500 cycles per SHA256 round, so I want future-promise construction, set_value and promise destruction to fit into a budget of about twenty CPU cycles.
I don't know if I'll achieve that, but that's my design goal. I want future promise to become really lightweight. shared_future will remain heavy for those who need it. Do you mean shared_ptr? The best when talking about performance is to have some figures :)
* I don't understand why when_all continuation has the futures as parameters (I suspect that this is a type on the documentation). * I would rename get_try to try_get. This function could return optional
. What are you missing ? * catch_error/recover that is already planed. * when_any I'd like to see any proposed C++ task system integrate well with ASIO. Tick that box for me and I am interested. Eliminate memory allocation and exception_ptr from the future-promise cycle and I am very interested indeed.
Good luck with your non-allocating future design. Vicente