178 lines
6.8 KiB
Markdown
178 lines
6.8 KiB
Markdown
[futures.state]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.10 Futures [[futures]](futures#state)
|
||
|
||
### 32.10.5 Shared state [futures.state]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11311)
|
||
|
||
Many of the classes introduced in subclause [[futures]](futures "32.10 Futures") use some state to communicate results[.](#1.sentence-1)
|
||
|
||
This
|
||
|
||
[*shared state*](#def:future,shared_state "32.10.5 Shared state [futures.state]") consists of some state information and some (possibly not
|
||
yet evaluated) [*result*](#def:result), which can be a (possibly void) value or an exception[.](#1.sentence-2)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Futures, promises, and tasks defined in this Clause reference such shared state[.](#1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11320)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
The result can be any kind of object including a function to compute that result,
|
||
as used by async when policy is launch::deferred[.](#2.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11326)
|
||
|
||
An [*asynchronous return object*](#def:asynchronous_return_object "32.10.5 Shared state [futures.state]") is an object that reads results from a
|
||
shared state[.](#3.sentence-1)
|
||
|
||
A [*waiting function*](#def:function,waiting "32.10.5 Shared state [futures.state]") of an asynchronous return object is one
|
||
that potentially blocks to wait for the shared state to be made
|
||
ready[.](#3.sentence-2)
|
||
|
||
If a waiting function can return before the state is made ready because of a
|
||
timeout ([[thread.req.lockable]](thread.req.lockable "32.2.5 Requirements for Cpp17Lockable types")), then it is a [*timed waiting function*](#def:timed_waiting_function), otherwise
|
||
it is a [*non-timed waiting function*](#def:non-timed_waiting_function)[.](#3.sentence-3)
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11335)
|
||
|
||
An [*asynchronous provider*](#def:asynchronous_provider "32.10.5 Shared state [futures.state]") is an object that provides a result to a shared
|
||
state[.](#4.sentence-1)
|
||
|
||
The result of a shared state is set by
|
||
respective functions on the asynchronous provider[.](#4.sentence-2)
|
||
|
||
[*Example [1](#example-1)*:
|
||
|
||
Promises and tasks are examples of asynchronous providers[.](#4.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
The means of setting the result of a shared state is specified
|
||
in the description of those classes and functions that create such a state object[.](#4.sentence-4)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11346)
|
||
|
||
When an asynchronous return object or an asynchronous provider is said to release its
|
||
shared state, it means:
|
||
|
||
- [(5.1)](#5.1)
|
||
|
||
if the return object or provider holds the last reference to its shared state,
|
||
the shared state is destroyed; and
|
||
|
||
- [(5.2)](#5.2)
|
||
|
||
the return object or provider gives up its reference to its shared state; and
|
||
|
||
- [(5.3)](#5.3)
|
||
|
||
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 tostd::async, the shared state is not yet ready, and this was the last reference
|
||
to the shared state[.](#5.sentence-1)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11363)
|
||
|
||
When an asynchronous provider is said to make its shared state ready, it means:
|
||
|
||
- [(6.1)](#6.1)
|
||
|
||
first, the provider marks its shared state as ready; and
|
||
|
||
- [(6.2)](#6.2)
|
||
|
||
second, the provider unblocks any execution agents waiting for its shared
|
||
state to become ready[.](#6.sentence-1)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11373)
|
||
|
||
When an asynchronous provider is said to abandon its shared state, it means:
|
||
|
||
- [(7.1)](#7.1)
|
||
|
||
first, if that state is not ready, the provider
|
||
* [(7.1.1)](#7.1.1)
|
||
|
||
stores an exception object of type future_error with an error condition ofbroken_promise within its shared state; and then
|
||
|
||
* [(7.1.2)](#7.1.2)
|
||
|
||
makes its shared state ready;
|
||
|
||
- [(7.2)](#7.2)
|
||
|
||
second, the provider releases its shared state[.](#7.sentence-1)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11389)
|
||
|
||
A shared state is [*ready*](#def:ready "32.10.5 Shared state [futures.state]") only if it holds a value or an exception ready for
|
||
retrieval[.](#8.sentence-1)
|
||
|
||
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[.](#8.sentence-2)
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11396)
|
||
|
||
Calls to functions that successfully set the stored result of a shared
|
||
state [synchronize with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") calls to functions
|
||
successfully detecting the ready state resulting from that setting[.](#9.sentence-1)
|
||
|
||
The storage of the result
|
||
(whether normal or exceptional) into the shared state[synchronizes with](intro.multithread#def:synchronize_with "6.10.2 Multi-threaded executions and data races [intro.multithread]") the successful return from a call to a waiting function on the shared state[.](#9.sentence-2)
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11405)
|
||
|
||
Some functions (e.g., promise::set_value_at_thread_exit) delay making
|
||
the shared state ready until the calling thread exits[.](#10.sentence-1)
|
||
|
||
The destruction of
|
||
each of that thread's objects with [thread storage duration](basic.stc.thread "6.8.6.3 Thread storage duration [basic.stc.thread]") is sequenced before making that shared state ready[.](#10.sentence-2)
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11411)
|
||
|
||
Access to the result of the same shared state may [conflict](intro.multithread#def:conflict "6.10.2 Multi-threaded executions and data races [intro.multithread]")[.](#11.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
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]](res.on.data.races "16.4.6.10 Data race avoidance"))[.](#11.sentence-2)
|
||
|
||
For example, concurrent accesses through
|
||
references returned by shared_future::get() ([[futures.shared.future]](futures.shared.future "32.10.8 Class template shared_future"))
|
||
must either use read-only operations or provide additional synchronization[.](#11.sentence-3)
|
||
|
||
â *end note*]
|