On 26 May 2015 11:54 am, "Peter Dimov"
Giovanni Piero Deretta wrote:
On 26 May 2015 12:59 am, "Peter Dimov"
wrote: This non-allocating implementation is an interesting argument in favor
of the current "unique future", which I've long disliked. I prefer >
futures to be shared_futures.
Interesting, why do you dislike the unique future design?
I dislike the unique/shared future split, which requires all algorithms to be duplicated/manyplicated.
auto f = when_any( f1, f2, f3, f4 ); // 2^4 options
The algorithm can be generic of course. You fear the template instantiation explosion? You'll have the same problem if you want to mix different futures from separate libraries.
A shared future pretty much requires holding a shared pointer and needs
heavy weight synchronisation ( a muted+condvar or equivalent). On the other hand a unique future need no internal mutual exclusion and the only synchronisation is needed for the handoff between producer and consumer; the reference count is implicit (just have the consumer always deallocate the object). The implementation can be significantly more light weight.
I already acknowledged that these implementations are an argument in
favor of unique future.
But I don't think I agree with what you're saying. I don't see how
mutex+condvar is required by shared future but not by unique future (how do you implement wait() is not related to sharedness), neither do I see how unique futures require no synchronization (they obviously do in Niall's implementation.) You are right of course. The readiness notification is orthogonal, but in a shared future you need a mutex to synchronise the various consumers access to the shared state, so a condition variable becomes the obvious choice, while you can be more creative with plain futures. Synchronisation with unique futures is of course necessary, but is much simpler: the producer will set the future to ready exactly once, then never touches it again, while the consumer won't access the future state until it is ready. Basically the producer need a single strong CAS on an atomic object to see the readiness and check for waiters, similarly the waiter need a CAS to test and wait. No explicit mutual exclusion is necessary.