367 lines
11 KiB
Markdown
367 lines
11 KiB
Markdown
[futures.promise]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.10 Futures [[futures]](futures#promise)
|
||
|
||
### 32.10.6 Class template promise [futures.promise]
|
||
|
||
[ð](#lib:promise)
|
||
|
||
namespace std {template<class R>class promise {public: promise(); template<class Allocator> promise(allocator_arg_t, const Allocator& a);
|
||
promise(promise&& rhs) noexcept;
|
||
promise(const promise&) = delete; ~promise(); // assignment promise& operator=(promise&& rhs) noexcept;
|
||
promise& operator=(const promise&) = delete; void swap(promise& other) noexcept; // retrieving the result future<R> get_future(); // setting the resultvoid set_value(*see below*); void set_exception(exception_ptr p); // setting the result with deferred notificationvoid set_value_at_thread_exit(*see below*); void set_exception_at_thread_exit(exception_ptr p); };}
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11455)
|
||
|
||
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[.](#1.sentence-1)
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11459)
|
||
|
||
The implementation provides the template promise and two specializations,promise<R&> and promise<void>[.](#2.sentence-1)
|
||
|
||
These differ only in the argument type
|
||
of the member functions set_value and set_value_at_thread_exit,
|
||
as set out in their descriptions, below[.](#2.sentence-2)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11465)
|
||
|
||
The set_value, set_exception, set_value_at_thread_exit,
|
||
and set_exception_at_thread_exit member functions behave as though
|
||
they acquire a single mutex associated with the promise object while updating the
|
||
promise object[.](#3.sentence-1)
|
||
|
||
[ð](#lib:promise,constructor)
|
||
|
||
`promise();
|
||
template<class Allocator>
|
||
promise(allocator_arg_t, const Allocator& a);
|
||
`
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11479)
|
||
|
||
*Effects*: Creates a shared state[.](#4.sentence-1)
|
||
|
||
The second
|
||
constructor uses the allocator a to allocate memory for the shared
|
||
state[.](#4.sentence-2)
|
||
|
||
[ð](#lib:promise,constructor_)
|
||
|
||
`promise(promise&& rhs) noexcept;
|
||
`
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11492)
|
||
|
||
*Effects*: Transfers ownership of the shared state
|
||
of rhs (if any) to the newly-constructed object[.](#5.sentence-1)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11497)
|
||
|
||
*Postconditions*: rhs has no shared state[.](#6.sentence-1)
|
||
|
||
[ð](#lib:promise,destructor)
|
||
|
||
`~promise();
|
||
`
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11508)
|
||
|
||
*Effects*: Abandons any shared state ([[futures.state]](futures.state "32.10.5 Shared state"))[.](#7.sentence-1)
|
||
|
||
[ð](#lib:operator=,promise)
|
||
|
||
`promise& operator=(promise&& rhs) noexcept;
|
||
`
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11519)
|
||
|
||
*Effects*: Abandons any shared state ([[futures.state]](futures.state "32.10.5 Shared state")) and then as ifpromise(std::move(rhs)).swap(*this)[.](#8.sentence-1)
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11524)
|
||
|
||
*Returns*: *this[.](#9.sentence-1)
|
||
|
||
[ð](#lib:swap,promise)
|
||
|
||
`void swap(promise& other) noexcept;
|
||
`
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11535)
|
||
|
||
*Effects*: Exchanges the shared state of *this and other[.](#10.sentence-1)
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11539)
|
||
|
||
*Postconditions*: *this has the shared state (if any) that other had
|
||
prior to the call to swap[.](#11.sentence-1)
|
||
|
||
other has the shared state (if any) that*this had prior to the call to swap[.](#11.sentence-2)
|
||
|
||
[ð](#lib:get_future,promise)
|
||
|
||
`future<R> get_future();
|
||
`
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11552)
|
||
|
||
*Synchronization*: Calls to this function do not introduce
|
||
data races ([[intro.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races")) with calls toset_value,set_exception,set_value_at_thread_exit, orset_exception_at_thread_exit[.](#12.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Such calls need not synchronize with each other[.](#12.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11564)
|
||
|
||
*Returns*: A future<R> object with the same shared state as*this[.](#13.sentence-1)
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11569)
|
||
|
||
*Throws*: future_error if *this has no shared state or ifget_future has already been called on a promise with the same
|
||
shared state as *this[.](#14.sentence-1)
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11575)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(15.1)](#15.1)
|
||
|
||
future_already_retrieved if get_future has already been called on
|
||
a promise with the same shared state as *this[.](#15.1.sentence-1)
|
||
|
||
- [(15.2)](#15.2)
|
||
|
||
no_state if *this has no shared state[.](#15.2.sentence-1)
|
||
|
||
[ð](#lib:set_value,promise)
|
||
|
||
`void promise::set_value(const R& r);
|
||
void promise::set_value(R&& r);
|
||
void promise<R&>::set_value(R& r);
|
||
void promise<void>::set_value();
|
||
`
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11594)
|
||
|
||
*Effects*: Atomically stores the value r in the shared state and
|
||
makes that state ready ([[futures.state]](futures.state "32.10.5 Shared state"))[.](#16.sentence-1)
|
||
|
||
[17](#17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11599)
|
||
|
||
*Throws*:
|
||
|
||
- [(17.1)](#17.1)
|
||
|
||
future_error if its shared state
|
||
already has a stored value or exception, or
|
||
|
||
- [(17.2)](#17.2)
|
||
|
||
for the first version, any exception thrown by the constructor selected to copy an object of R, or
|
||
|
||
- [(17.3)](#17.3)
|
||
|
||
for the second version, any exception thrown by the constructor selected to move an object of R[.](#17.sentence-1)
|
||
|
||
[18](#18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11608)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(18.1)](#18.1)
|
||
|
||
promise_already_satisfied if its shared state
|
||
already has a stored value or exception[.](#18.1.sentence-1)
|
||
|
||
- [(18.2)](#18.2)
|
||
|
||
no_state if *this has no shared state[.](#18.2.sentence-1)
|
||
|
||
[ð](#lib:set_exception,promise)
|
||
|
||
`void set_exception(exception_ptr p);
|
||
`
|
||
|
||
[19](#19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11623)
|
||
|
||
*Preconditions*: p is not null[.](#19.sentence-1)
|
||
|
||
[20](#20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11627)
|
||
|
||
*Effects*: Atomically stores the exception pointer p in the shared state
|
||
and makes that state ready ([[futures.state]](futures.state "32.10.5 Shared state"))[.](#20.sentence-1)
|
||
|
||
[21](#21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11632)
|
||
|
||
*Throws*: future_error if its shared state
|
||
already has a stored value or exception[.](#21.sentence-1)
|
||
|
||
[22](#22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11637)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(22.1)](#22.1)
|
||
|
||
promise_already_satisfied if its shared state
|
||
already has a stored value or exception[.](#22.1.sentence-1)
|
||
|
||
- [(22.2)](#22.2)
|
||
|
||
no_state if *this has no shared state[.](#22.2.sentence-1)
|
||
|
||
[ð](#lib:set_value_at_thread_exit,promise)
|
||
|
||
`void promise::set_value_at_thread_exit(const R& r);
|
||
void promise::set_value_at_thread_exit(R&& r);
|
||
void promise<R&>::set_value_at_thread_exit(R& r);
|
||
void promise<void>::set_value_at_thread_exit();
|
||
`
|
||
|
||
[23](#23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11655)
|
||
|
||
*Effects*: Stores the value r in the shared state without making that
|
||
state ready immediately[.](#23.sentence-1)
|
||
|
||
Schedules that state to be made ready when the current
|
||
thread exits, after all objects with thread storage duration associated with the
|
||
current thread have been destroyed[.](#23.sentence-2)
|
||
|
||
[24](#24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11662)
|
||
|
||
*Throws*:
|
||
|
||
- [(24.1)](#24.1)
|
||
|
||
future_error if its shared state
|
||
already has a stored value or exception, or
|
||
|
||
- [(24.2)](#24.2)
|
||
|
||
for the first version, any exception thrown by the constructor selected to copy an object of R, or
|
||
|
||
- [(24.3)](#24.3)
|
||
|
||
for the second version, any exception thrown by the constructor selected to move an object of R[.](#24.sentence-1)
|
||
|
||
[25](#25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11671)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(25.1)](#25.1)
|
||
|
||
promise_already_satisfied if its shared state
|
||
already has a stored value or exception[.](#25.1.sentence-1)
|
||
|
||
- [(25.2)](#25.2)
|
||
|
||
no_state if *this has no shared state[.](#25.2.sentence-1)
|
||
|
||
[ð](#lib:set_exception_at_thread_exit,promise)
|
||
|
||
`void set_exception_at_thread_exit(exception_ptr p);
|
||
`
|
||
|
||
[26](#26)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11686)
|
||
|
||
*Preconditions*: p is not null[.](#26.sentence-1)
|
||
|
||
[27](#27)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11690)
|
||
|
||
*Effects*: Stores the exception pointer p in the shared state without
|
||
making that state ready immediately[.](#27.sentence-1)
|
||
|
||
Schedules that state to be made ready when
|
||
the current thread exits, after all objects with thread storage duration
|
||
associated with the current thread have been destroyed[.](#27.sentence-2)
|
||
|
||
[28](#28)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11697)
|
||
|
||
*Throws*: future_error if an error condition occurs[.](#28.sentence-1)
|
||
|
||
[29](#29)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11701)
|
||
|
||
*Error conditions*:
|
||
|
||
- [(29.1)](#29.1)
|
||
|
||
promise_already_satisfied if its shared state
|
||
already has a stored value or exception[.](#29.1.sentence-1)
|
||
|
||
- [(29.2)](#29.2)
|
||
|
||
no_state if *this has no shared state[.](#29.2.sentence-1)
|
||
|
||
[ð](#lib:swap,promise_)
|
||
|
||
`template<class R>
|
||
void swap(promise<R>& x, promise<R>& y) noexcept;
|
||
`
|
||
|
||
[30](#30)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11717)
|
||
|
||
*Effects*: As if by x.swap(y)[.](#30.sentence-1)
|