33 Thread support library [thread]

33.6 Futures [futures]

33.6.7 Class template future [futures.unique_future]

The class template future defines a type for asynchronous return objects which do not share their shared state with other asynchronous return objects. A default-constructed future object has no shared state. A future object with shared state can be created by functions on asynchronous providers or by the move constructor and shares its shared state with the original asynchronous provider. The result (value or exception) of a future object can be set by calling a respective function on an object that shares the same shared state.

[Note: Member functions of future do not synchronize with themselves or with member functions of shared_­future. end note]

The effect of calling any member function other than the destructor, the move-assignment operator, share, or valid on a future object for which valid() == false is undefined. [Note: It is valid to move from a future object for which valid() == false. end note] [Note: Implementations are encouraged to detect this case and throw an object of type future_­error with an error condition of future_­errc​::​no_­state. end note]

namespace std {
  template <class R>
  class future {
  public:
    future() noexcept;
    future(future&&) noexcept;
    future(const future& rhs) = delete;
    ~future();
    future& operator=(const future& rhs) = delete;
    future& operator=(future&&) noexcept;
    shared_future<R> share() noexcept;

    // retrieving the value
    see below get();

    // functions to check state
    bool valid() const noexcept;

    void wait() const;
    template <class Rep, class Period>
      future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
    template <class Clock, class Duration>
      future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
  };
}

The implementation shall provide the template future and two specializations, future<R&> and future<​void>. These differ only in the return type and return value of the member function get, as set out in its description, below.

future() noexcept;

Effects: Constructs an empty future object that does not refer to a shared state.

Postconditions: valid() == false.

future(future&& rhs) noexcept;

Effects: Move constructs a future object that refers to the shared state that was originally referred to by rhs (if any).

Postconditions:

  • valid() returns the same value as rhs.valid() prior to the constructor invocation.

  • rhs.valid() == false.

~future();

Effects:

future& operator=(future&& rhs) noexcept;

Effects:

Postconditions:

  • valid() returns the same value as rhs.valid() prior to the assignment.

  • rhs.valid() == false.

shared_future<R> share() noexcept;

Returns: shared_­future<R>(std​::​move(*this)).

Postconditions: valid() == false.

R future::get(); R& future<R&>::get(); void future<void>::get();

[Note: As described above, the template and its two required specializations differ only in the return type and return value of the member function get. end note]

Effects:

  • wait()s until the shared state is ready, then retrieves the value stored in the shared state;

  • releases any shared state ([futures.state]).

Returns:

  • future​::​get() returns the value v stored in the object's shared state as std​::​move(v).

  • future<R&>​::​get() returns the reference stored as value in the object's shared state.

  • future<void>​::​get() returns nothing.

Throws: the stored exception, if an exception was stored in the shared state.

Postconditions: valid() == false.

bool valid() const noexcept;

Returns: true only if *this refers to a shared state.

void wait() const;

Effects: Blocks until the shared state is ready.

template <class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;

Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the relative timeout ([thread.req.timing]) specified by rel_­time has expired.

Returns:

  • future_­status​::​deferred if the shared state contains a deferred function.

  • future_­status​::​ready if the shared state is ready.

  • future_­status​::​timeout if the function is returning because the relative timeout ([thread.req.timing]) specified by rel_­time has expired.

Throws: timeout-related exceptions ([thread.req.timing]).

template <class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;

Effects: None if the shared state contains a deferred function ([futures.async]), otherwise blocks until the shared state is ready or until the absolute timeout ([thread.req.timing]) specified by abs_­time has expired.

Returns:

  • future_­status​::​deferred if the shared state contains a deferred function.

  • future_­status​::​ready if the shared state is ready.

  • future_­status​::​timeout if the function is returning because the absolute timeout ([thread.req.timing]) specified by abs_­time has expired.

Throws: timeout-related exceptions ([thread.req.timing]).