Many of the classes introduced in subclause [futures] use some state to communicate results.
This
shared state consists of some state information and some (possibly not
yet evaluated) result, which can be a (possibly void) value or an exception.
these actions will not block for the shared state to become ready, except that it
may block if all of the following are true: the shared state was created by a call to
std::async, the shared state is not yet ready, and this was the last reference
to the shared state.
A shared state is ready only if it holds a value or an exception ready for
retrieval.
Waiting for a shared state to become ready may invoke code to compute the result on
the waiting thread if so specified in the description of the class or function that creates
the state object.
Calls to functions that successfully set the stored result of a shared
state synchronize with calls to functions
successfully detecting the ready state resulting from that setting.
The storage of the result
(whether normal or exceptional) into the shared state
synchronizes with
the successful return from a call to a waiting function on the shared state.
This explicitly specifies that the result of the shared state is
visible in the objects that reference this state in the sense of data race
avoidance ([res.on.data.races]).
For example, concurrent accesses through
references returned by shared_future::get() ([futures.shared.future])
must either use read-only operations or provide additional synchronization.