
On 3/14/07, Hartmut Kaiser <hartmut.kaiser@gmail.com> wrote:
[about combining mutexes] But as soon as you start combining || and && this isn't always possible anymore. Additional optimization can be done, if all futures in a operator|| sequence return the same type, in which case you don't need to use a variant.
Instead of going with generalized future composition, I've tried the route of 'wait_all(<future-list>) ' and 'wait_any(<future-tuple>)' Sure, it is less flexible than overloading || and && and permitting complex expressions, but it is easy to implement, its behavior as a blocking point is immediate and most importantly it is simple to understand. If you really need to wait for multiple futures with complex patterns, simply use a full blown reactor (i.e. asio).
Should there be a seperate future_group concept to disambiguate?
What do you mean by that?
Composition overloading with || or && gets very hairy or impossible if the current proposal to have a future implicitly convertable to it's value, with blocking, goes through. Maybe Peter has thoughts on this.
I personally don't like the idea of having the future convert implicitely to its value type at all. I'm not sure if this can be implemented completely fail proof without ruunning in surprising behavior.
I agree. What about an optional<T> like interface for future<T>? you can do: future<some_type1> a = async_op1(...); some_type1 xa = *a; //may block if not yet ready or, as a more convoluted example: future<some_type1> a = async_op1(...); future<some_type2> b = async_op2(...); future<void> timeout = post_timer(timeout); while(true){ wait_any(a, b,c) if(a) { some_type1 xa = *a; // guaranteed not to block // do something with xa } if(b) { some_type2 xb = *b; // guaranteed not to block // do something with xb } if((a && b) || timeout) { //no boolean operator overloading here, just plain builtins a.cancel(); //no-op if already completed. b.cancel(); //ditto break; } }
I like the tuples/variant idea of composition, but how do you handle exceptions?
In this case wait_any could report a failed future as ready. operator* would throw the forwarded exception. Not sure about that though. The futures I had implemented didn't support exception forwarding. gpd