[futures.shared.future]

# 32 Concurrency support library [[thread]](./#thread)

## 32.10 Futures [[futures]](futures#shared.future)

### 32.10.8 Class template shared_future [futures.shared.future]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12031)

The class template shared_future defines a type for asynchronous return objects
which may share their shared state with other asynchronous return
objects[.](#1.sentence-1)

A default-constructed shared_future object has no shared state[.](#1.sentence-2)

A shared_future object with
shared state can
be created
by conversion from a future object and shares its shared state with the
original [asynchronous provider](futures.state#def:asynchronous_provider "32.10.5 Shared state [futures.state]") of the shared state[.](#1.sentence-3)

The result (value or exception) of a shared_future object
can be set by
calling a respective function on an
object that shares the same shared state[.](#1.sentence-4)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12045)

[*Note [1](#note-1)*:

Member functions of shared_future do not synchronize with themselves,
but they synchronize with the shared state[.](#2.sentence-1)

â *end note*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12051)

The effect of calling any member function other than the destructor,
the move assignment operator, the copy assignment operator, orvalid() on a shared_future object for which valid() == false is undefined[.](#3.sentence-1)

[*Note [2](#note-2)*:

It is valid to copy or move from a shared_future object for which valid() is false[.](#3.sentence-2)

â *end note*]

*Recommended practice*: Implementations should detect this case and throw an object of typefuture_error with an error condition of future_errc​::​no_state[.](#3.sentence-3)

[ð](#lib:shared_future)

namespace std {template<class R>class shared_future {public: shared_future() noexcept;
 shared_future(const shared_future& rhs) noexcept;
 shared_future(future<R>&&) noexcept;
 shared_future(shared_future&& rhs) noexcept; ~shared_future();
 shared_future& operator=(const shared_future& rhs) noexcept;
 shared_future& operator=(shared_future&& rhs) noexcept; // retrieving the value*see below* get() const; // functions to check statebool 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; };}

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12093)

For the primary template, R shall be an object type that
meets the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements[.](#4.sentence-1)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12097)

The implementation provides the template shared_future and two
specializations, shared_future<R&> and shared_future<void>[.](#5.sentence-1)

These
differ only in the return type and return value of the member function get, as
set out in its description, below[.](#5.sentence-2)

[ð](#lib:shared_future,constructor)

`shared_future() noexcept;
`

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12109)

*Effects*: The object does not refer to a shared state[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12113)

*Postconditions*: valid() == false[.](#7.sentence-1)

[ð](#lib:shared_future,constructor_)

`shared_future(const shared_future& rhs) noexcept;
`

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12124)

*Effects*: The object refers to the same
shared state as rhs (if any)[.](#8.sentence-1)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12129)

*Postconditions*: valid() returns the same value as rhs.valid()[.](#9.sentence-1)

[ð](#lib:shared_future,constructor__)

`shared_future(future<R>&& rhs) noexcept;
shared_future(shared_future&& rhs) noexcept;
`

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12141)

*Effects*: Move constructs a shared_future object that refers to the
shared state that was originally referred to by rhs (if any)[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12146)

*Postconditions*: 

- [(11.1)](#11.1)

  valid() returns the same value as rhs.valid() returned prior to
the constructor invocation[.](#11.1.sentence-1)

- [(11.2)](#11.2)

  rhs.valid() == false[.](#11.2.sentence-1)

[ð](#lib:shared_future,destructor)

`~shared_future();
`

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12161)

*Effects*: 

- [(12.1)](#12.1)

Releases any shared state ([[futures.state]](futures.state "32.10.5 Shared state"));

- [(12.2)](#12.2)

destroys *this[.](#12.sentence-1)

[ð](#lib:operator=,shared_future)

`shared_future& operator=(shared_future&& rhs) noexcept;
`

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12177)

*Effects*: If addressof(rhs) == this is true, there are no effects[.](#13.sentence-1)

Otherwise:

- [(13.1)](#13.1)

Releases any shared state ([[futures.state]](futures.state "32.10.5 Shared state"));

- [(13.2)](#13.2)

move assigns the contents of rhs to *this[.](#13.sentence-2)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12188)

*Postconditions*: 

- [(14.1)](#14.1)

  valid() returns the same value as rhs.valid() returned prior to
the assignment[.](#14.1.sentence-1)

- [(14.2)](#14.2)

  If addressof(rhs) == this is false,rhs.valid() == false[.](#14.2.sentence-1)

[ð](#lib:operator=,shared_future_)

`shared_future& operator=(const shared_future& rhs) noexcept;
`

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12207)

*Effects*: If addressof(rhs) == this is true, there are no effects[.](#15.sentence-1)

Otherwise:

- [(15.1)](#15.1)

Releases any shared state ([[futures.state]](futures.state "32.10.5 Shared state"));

- [(15.2)](#15.2)

assigns the contents of rhs to *this[.](#15.sentence-2)
  [*Note [3](#note-3)*:
  As a result,*this refers to the same shared state as rhs (if any)[.](#15.2.sentence-2)
 â *end note*]

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12223)

*Postconditions*: valid() == rhs.valid()[.](#16.sentence-1)

[ð](#lib:get,shared_future)

`const R& shared_future::get() const;
R& shared_future<R&>::get() const;
void shared_future<void>::get() const;
`

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12236)

[*Note [4](#note-4)*:

As described above, the template and its two required specializations differ only in
the return type and return value of the member function get[.](#17.sentence-1)

â *end note*]

[18](#18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12242)

[*Note [5](#note-5)*:

Access to a value object stored in the shared state is
unsynchronized, so operations on R might
introduce a data race ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#18.sentence-1)

â *end note*]

[19](#19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12249)

*Effects*: wait()s until the shared state is ready, then retrieves the
value stored in the shared state[.](#19.sentence-1)

[20](#20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12254)

*Returns*: 

- [(20.1)](#20.1)

  shared_future​::​get() returns a const reference to the value stored in the object's
shared state[.](#20.1.sentence-1)
  [*Note [6](#note-6)*:
  Access through that reference after the shared state has been
destroyed produces undefined behavior; this can be avoided by not storing the reference in any
storage with a greater lifetime than the shared_future object that returned the
reference[.](#20.1.sentence-2)
 â *end note*]

- [(20.2)](#20.2)

  shared_future<R&>​::​get() returns the reference stored as value in the object's
shared state[.](#20.2.sentence-1)

- [(20.3)](#20.3)

  shared_future<void>​::​get() returns nothing[.](#20.3.sentence-1)

[21](#21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12275)

*Throws*: The stored exception, if an exception was stored in the shared state[.](#21.sentence-1)

[ð](#lib:valid,shared_future)

`bool valid() const noexcept;
`

[22](#22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12286)

*Returns*: true only if *this refers to a shared state[.](#22.sentence-1)

[ð](#lib:wait,shared_future)

`void wait() const;
`

[23](#23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12297)

*Effects*: Blocks until the shared state is ready[.](#23.sentence-1)

[ð](#lib:wait_for,shared_future)

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

[24](#24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12310)

*Effects*: None if the shared state contains a deferred function ([[futures.async]](futures.async "32.10.9 Function template async")),
otherwise
blocks until the shared state is ready or until
the relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified byrel_time has expired[.](#24.sentence-1)

[25](#25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12319)

*Returns*: 

- [(25.1)](#25.1)

  future_status​::​deferred if the shared state contains a deferred
function[.](#25.1.sentence-1)

- [(25.2)](#25.2)

  future_status​::​ready if the shared state is ready[.](#25.2.sentence-1)

- [(25.3)](#25.3)

  future_status​::​timeout if the function is returning because the
relative timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))
specified by rel_time has expired[.](#25.3.sentence-1)

[26](#26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12332)

*Throws*: timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#26.sentence-1)

[ð](#lib:wait_until,shared_future)

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

[27](#27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12344)

*Effects*: None if the shared state contains a deferred function ([[futures.async]](futures.async "32.10.9 Function template async")),
otherwise
blocks until the shared state is ready or until the
absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")) specified byabs_time has expired[.](#27.sentence-1)

[28](#28)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12353)

*Returns*: 

- [(28.1)](#28.1)

  future_status​::​deferred if the shared state contains a deferred
function[.](#28.1.sentence-1)

- [(28.2)](#28.2)

  future_status​::​ready if the shared state is ready[.](#28.2.sentence-1)

- [(28.3)](#28.3)

  future_status​::​timeout if the function is returning because the
absolute timeout ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))
specified by abs_time has expired[.](#28.3.sentence-1)

[29](#29)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L12366)

*Throws*: timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))[.](#29.sentence-1)
