future/shared_future
unwrapping constructor when given an invalid future
Section: 99 [concurr.ts::futures.unique_future], 99 [concurr.ts::futures.shared_future] Status: C++23 Submitter: Tim Song Opened: 2016-04-22 Last modified: 2023-11-22
Priority: 2
View all issues with C++23 status.
Discussion:
Addresses: concurr.ts
In the concurrency TS, the future/shared_future unwrapping constructors
future(future<future<R>>&&) noexcept; shared_future(future<shared_future<R>>&& rhs) noexcept;
appear to implicitly require rhs
be valid (e.g., by referring to its shared state, and by requiring a
valid() == true
postcondition). However, they are also marked noexcept
, suggesting that they
are wide-contract, and also makes the usual suggested handling for invalid futures, throwing a
future_error
, impossible.
noexcept
should be removed, or the behavior with an invalid future should be specified.
Original resolution alternative #1 [NOT CHOSEN]:
This wording is relative to N4577.
Strike the
noexcept
on these constructors in 99 [concurr.ts::futures.unique_future]/1-2 and 99 [concurr.ts::futures.shared_future]/1-2, and optionally add a Requires:rhs.valid() == true
paragraph.
[2016-11-12, Issaquah]
Sat PM: We prefer alternative #2 - Move to review
[2018-06; Rapperswil, Wednesday evening session]
DR: there is a sentence ended followed by an entirely new sentence
JM: so the period should be a semicolon in both edits
MC: ACTION I can make the change editorially
ACTION move to Ready
[2018-11, Adopted in San Diego]
Proposed resolution:
This wording is relative to N4577.
Alternative #2: Specify that an empty (
shared_
)future
object is constructed ifrhs
is invalid, and adjust the postcondition accordingly.
Edit 99 [concurr.ts::futures.unique_future] as indicated:
future(future<future<R>>&& rhs) noexcept;-3- Effects: If
rhs.valid() == false
, constructs an emptyfuture
object that does not refer to a shared state. Otherwise, cConstructs afuture
object from the shared state referred to byrhs
. T; thefuture
becomes ready when one of the following occurs:
Both the
rhs
andrhs.get()
are ready. The value or the exception fromrhs.get()
is stored in thefuture
's shared state.
rhs
is ready butrhs.get()
is invalid. An exception of typestd::future_error
, with an error condition ofstd::future_errc::broken_promise
is stored in thefuture
's shared state.-4- Postconditions:
valid() == true
valid()
returns the same value asrhs.valid()
prior to the constructor invocation..
rhs.valid() == false
.
Edit 99 [concurr.ts::futures.shared_future] as indicated:
shared_future(future<shared_future<R>>&& rhs) noexcept;-3- Effects: If
rhs.valid() == false
, constructs an emptyshared_future
object that does not refer to a shared state. Otherwise, cConstructs ashared_future
object from the shared state referred to byrhs
. T; theshared_future
becomes ready when one of the following occurs:
Both the
rhs
andrhs.get()
are ready. The value or the exception fromrhs.get()
is stored in theshared_future
's shared state.
rhs
is ready butrhs.get()
is invalid. Theshared_future
stores an exception of typestd::future_error
, with an error condition ofstd::future_errc::broken_promise
.-4- Postconditions:
valid() == true
valid()
returns the same value asrhs.valid()
prior to the constructor invocation..
rhs.valid() == false
.