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 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.
The continuation takes the value and not the future. So a future can have several continuations. 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>.
The ability to return an optional from potentially blocking functions I think is nice. Very Rust. I'll have the same in my upcoming lightweight future-promise - as you correctly observed, my monad<T> is also an optional<T> with the right template alias.
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. 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. 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.
* 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. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/