Future result() and wait() should return tuples iff ...

Issue #123 resolved
john bachan created an issue

Would we like to change the return types of result/wait to make the following our idiomatic code for dealing with both single and multi-valued futures?

future<> f0;
future<A> f1;
future<A,B> f2;

f0.wait(); // return=void

A x = f1.wait(); // return=A

A a; B b;
std::tie(a,b) = f2.wait(); // return=tuple<A,B>
a = f2.wait<0>(); // return=A
b = f2.wait<1>(); // return=B

This would entail changing the default value for the component index template argument from zero to something "smart".

template<typename ...T>
struct future {
  template<int ix = -1>
  auto result() -> decltype(<goop>);

  template<int ix = -1>
  auto wait() -> decltype(<goop>);

  // where goop return is:
  //   if 0 <= ix < sizeof...(T)
  //     T...[ix] 
  //   if sizeof...(T) <= ix
  //     void
  //   if ix == -1 and sizeof...(T) > 1
  //     std::tuple<T...>
  //   if ix == -1 and sizeof...(T) == 1
  //     T...[0]
  //   if ix == -1 and sizeof...(T) == 0
  //     void
};

Comments (4)

  1. Dan Bonachea

    I'd really like to see future::wait*() and future::result*() have analogous interfaces (ie same template args and return type behaviors) - where the only difference between analogous calls in the two function "families" is the first stalls for readiness as needed, and the second requires readiness as a precondition.

    One way to accomplish this design symmetry is John's proposal that adds fancy return type "goop" to both future::wait() and future::result(). If we go that route we should probably also deprecate/remove future::result_tuple(), which will thereby become obsolete. (BTW I'm assuming John meant the return type to be a tuple reference std::tuple<T...>&, as is currently the case for result_tuple, not std::tuple<T...>)

    An alternative and potentially simpler way to achieve design symmetry and handle the use case in question is to introduce a wait_tuple() to mirror the behavior of future::result_tuple() (which we'd then keep), ie:

    template <typename ...T> 
    std::tuple <T...> const& future <T...>::wait_tuple() const;
    
    // Waits for the future by repeatedly attempting UPC++ user-level progress and 
    // testing for readiness. See Ch. 10 for a discussion of progress. The return value 
    // is the same as that produced by calling result_tuple() on the future. 
    

    We should discuss the merits of each possible design, both in terms of user programmability and implementation impact.

    Finally, we should consider whether it makes sense to expose a future::wait_moved() for symmetry with future::result_moved().

  2. Log in to comment