| Document Number: | N3058=10-0048 |
| Date: | 2010-03-11 |
| Project: | Programming Language C++ |
Detlef Vollmann <dv@vollmann.ch>
The adoption of N2996 and N2997 at the same meeting caused some editorial trouble, as the papers both were based on the previous working paper and were not properly aligned. [Big apologies to the editor!]
This paper tries to clean up the whole [futures] sub-clause.
Thanks to Anthony Williams, Jonathan Wakely, Daniel Krügler, Alisdair Meredith, José Daniel García Sánchez, Hans Boehm, Pete Becker, Alberto Ganesh Barbati and the Concurrency subgroup for their comments and contributions to this paper.
Apart from a number of editor's notes, this proposal resolves the following LWG issues:
1090 (Ready, added swap to header, otherwise copied verbatim)
1226 (Ready, copied verbatim)
1244 (New, agreed on enum return)
1266 (New, taken proposed semantics, but different wording, ok'ed by Anthony)
1269 (New, different wording, same semantics, ok'ed by Anthony)
1272 (New, proposed resolution copied verbatim)
1273 (Ready, proposed resolution copied verbatim)
1274 (Ready, proposed resolution copied verbatim)
1275 (New, suggestions from issue taken and created wording
1291 (New, proposed resolution copied with editorial change
1300 (Ready, proposed resolution copied verbatim)
1304 (Ready, proposed resolution copied verbatim)
1305 (New, proposed resolution partly taken)
1315 (Ready, proposed resolution copied verbatim)
decay_copy()) was already applied to the working paper.
Add a new enumeration future_status to 30.6.1 [futures.overview]
following the definition of the launch enumeration:
enum class future_status {
ready,
timeout,
deferred
};
In 30.6.1 [futures.overview], header <future> synopsis:
Change:
constexpr error_code make_error_code(future_errc e);
constexpr error_condition make_error_condition(future_errc e);
extern const error_category*& const future_category();
In 30.6.1 [futures.overview], header <future> synopsis, after declaration of class template packaged_task:
Add:
template <class R>
void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&)
In 30.6.1 [futures.overview], header <future> synopsis:
Change:
template <class F, class... Args>
future<typename F::result_typeresult_of<F(Args...)>::type>
async(F&& f, Args&&... args);
template <class F, class... Args>
future<typename F::result_typeresult_of<F(Args...)>::type>
async(launch policy, F&& f, Args&&... args);
In 30.6.2 [futures.errors] near paragraph 1:
Change:
externconst error_category&* constfuture_category();
future_category shall point to a statically initialized
object of a type derived from class error_category.error_category.
constexprerror_code make_error_code(future_errc e);
error_code(static_cast<int>(e),
*future_category()).
constexprerror_codecondition make_error_condition(future_errc e);
error_condition(static_cast<int>(e),
*future_category()).
In 30.6.4 [futures.state], title:
Change:
Associated asynchronous state
In 30.6.4 [futures.state], paragraph 1ff:
Change:
If fully initialized,
objects of type
future ([future.future]),
shared_future ([future.shared_future]),
atomic_future ([future.atomic_future]),
promise ([future.promise) and
packaged_task ([future.task])
reference
some state that is potentially shared between several such objects.
Many of the classes introduced in this sub-clause use some state
to communicate results.
This associated asynchronous state consists of some
state information and some (possibly not yet evaluated) result, which
can be a (possibly void) value or an exception.
[Note:
Futures, promises and tasks defined in this clause reference such
associated asynchronous state. --end note]
[Note:
The result can be any kind of object including a function to compute
that result, as used by async for
policy = launch::sync.
--end note]
Objects that read results from associated asynchronous state are called asynchronous return objects.
Objects that provide such a result, are called
asynchronous providers.
The result of such an associated asynchronous state
can be is set by
respective functions on the asynchronous provider.
[Note: Such as promises or tasks. --end note]
The means of setting the result of an associated asynchronous state is
specified in the description of those classes and functions that create
such a state object.
promise::set_value,promise::set_exception orpackaged_task::operator()
When the last reference to an associated asynchronous state is given up, any resources held by this associated asynchronous state are released.
An associated asynchronous state is ready only if it holds a value or an exception ready for retrieval. Waiting for an associated asynchronous 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 such a state object.
TheCalls to functions that successfully set the stored
result of an
associated asynchronous state synchronize with ([intro.multithread])
calls to member functions of other objects referring to
successfully detecting the ready status resulting from that
setting the same
associated asynchronous state and such calls are serialized.
The storage of the result (whether normal or exceptional) into the
associated asynchronous state happens-before ([intro.multithread])
that state is set to ready.
Accesses to the same associated asynchronous state
through member functions of
conflict ([intro.multithread]).
future, shared_future,
atomic_future, promise
or packaged_task objects
In 30.6.5 [futures.promise], synopsis:
Remove:
void set_value(const R& r);
In 30.6.5 [futures.promise], paragraph 3, promise():
Change:
promise object and an associated
asynchronous state.
The second constructor uses the allocator a
to allocate memory for the associated asynchronous state.
In 30.6.5 [futures.promise], paragraph 4f, promise(promise &&):
Change:
promise object and
transfers ownership of the associated asynchronous state of
rhs (if any) to the newly-constructed object.
rhs has no associated asynchronous state.
In 30.6.5 [futures.promise], paragraph 7, ~promise():
Change:
*this is
not ready, stores an exception of type future_error
with an error broken_promise>this->set_exception(copy_exception(future_error(future_errc::broken_promise)))*this to become ready are unblocked.
*this and releases its reference to its
associated asynchronous state if any. If this is the last reference
to that associated asynchronous state, destroys that state.
In 30.6.5 [futures.promise], paragraph 9, operator=():
Change:
rhs has no associated asynchronousstate.
*this has the associated asynchronous state of
rhs prior to the assignment.
In 30.6.5 [futures.promise], paragraph 12ff, swap():
Change:
swap(*this, other)*this and other.
*this has the same associated asynchronous state
(if any) as other prior to the call
to swap. other has the same associated
asynchronous state (if any) as *this prior to the call
to swap.
In 30.6.5 [futures.promise], paragraph 14ff, get_future():
Change:
future<R> object with the same associated
asynchronous state as *this.
future_error if *this has no associated
asynchronous state, or if get_future() has already
been called on a promise with the associated
asynchronous state of *this.
future_already_retrieved if get_future
has already been called on
a promise with the associated asynchronous state
of *this.no_state if *this has no associated
asynchronous state.
In 30.6.5 [futures.promise], before paragraph 17, set_value():
Change:
void promise::set_value(const R& r);
In 30.6.5 [futures.promise], paragraph 17ff, set_value():
Change:
r in the associated asynchronous
state and sets that state to ready.
Any threads blocked in a call of a blocking function of any future that
refers to the same associated asynchronous
state as *this are unblocked.
future_error if its associated asynchronous state
is already ready or,
R, orR.promise_already_satisfied if its associated
asynchronous state is already ready.no_state if *this has no associated
asynchronousstate.set_value and set_exception on
a single promise object are serialized.
In 30.6.5 [futures.promise], paragraph 21ff, set_exception():
Change:
p in the associated asynchronous
state and sets that state to ready. Any threads blocked in a call of a
blocking function of any future that refers to the same associated
asynchronous state as *this are unblocked.
future_error if its associated asynchronous state
is already ready.
promise_already_satisfied if its associated
asynchronous state is already ready.no_state if *this has no associated
asynchronousstate.set_value and set_exception on
a single promise object are serialized.
In 30.6.6 [futures.unique_future], paragraph 1:
Change:
The class template future defines a type for
asynchronous return objects which do not share their associated
asynchronous state with other asynchronous return objects.
A default-constructed future has no
associated asynchronous state. future objects with
associated asynchronous state can only be created by
use of
functions on asynchronous providers ([futures.state] or by the move
constructor and share their associated asynchronous state
with
promise ([future.promise]) or
packaged_task ([future.task]) objects,that
the original asynchronous provider.
The result (values or exceptions) of promise or packaged_task. Theirfuture objects
can be set by
use of the
calling a respective function on an
object that shares the same associated asynchronous state.
promise
([future.promise]) or packaged_task ([future.task])
In 30.6.6 [futures.unique_future], paragraph 3, introduction:
Change:
The effect of calling any member function other than the destructor
or the move-assignment operator or valid() on a
future for which valid() == false is undefined.
In 30.6.6 [futures.unique_future], after paragraph 3, synopsis:
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
future():Change:
future that
In 30.6.6 [futures.unique_future], paragraph 7, future(future&&):
Change:
future object that refers to the
associated asynchronous state that was originally
referred to by rhs (if any).
In 30.6.6 [futures.unique_future], paragraph 10, ~future():
Change:
*this.
In 30.6.6 [futures.unique_future], paragraph 12, operator=():
Change:
*this referred to an associated asynchronous
state prior to the assignment it gives up this reference.rhs to*this.
In 30.6.6 [futures.unique_future], paragraph 15ff, get():
Change:
wait()s until the associated asynchronous
state is ready.future::get() returns the value
stored in the object's associated asynchronous state.future<R&>::get() returns the reference stored
as value in the object's associated asynchronous state.future<void>::get() returns nothing.
In 30.6.6 [futures.unique_future], paragraph 19, valid():
Change:
true only if *this refers to an associated
asynchronous state.
In 30.6.6 [futures.unique_future], paragraph 21, wait():
Change:
In 30.6.6 [futures.unique_future], before paragraph 22, wait_for:
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
In 30.6.6 [futures.unique_future], paragraph 23f, wait_for:
Change:
rel_time has elapsed.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time period specified
by rel_time has elapsed.
In 30.6.6 [futures.unique_future], before paragraph 25, wait_until:
Change:
template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
In 30.6.6 [futures.unique_future], paragraph 26f, wait_until:
Change:
abs_time.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time point specified
by abs_time has been reached.
In 30.6.7 [future.shared_future], paragraph 1f, introduction:
Change:
The class template shared_future defines a type for
asynchronous return objects which may share their associated
asynchronous state with other asynchronous return objects.
A default-constructed shared_future has no associated
asynchronous state.
A shared_future object with associated asynchronous
state can only be created
from another
by conversion from a shared_future with
associated state or a future object with
associated statefuture object
and share their associated asynchronous state with the original
asynchronous provider of the associated state.
TheirThe result (values or exceptions) of
shared_future objects
can be set by
use of a
calling a respective function on an object that
shares the same associated asynchronous state.
promise ([future.promise])
or packaged_task ([future.task])
[Note:shared_future member functions do not
synchronize with themselves, but they synchronize on the shared
associated asynchronous state. --end note]
The effect of calling any member function other than
the destructor or the move-assignment operator or
valid() on a shared_future for
which valid() == false is undefined.
In 30.6.7 [future.shared_future], after paragraph 2, synopsis:
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
In 30.6.7 [future.shared_future], paragraph 4, shared_future():
Change:
shared_future that doesn't
refer to an associated asynchronous state.
valid() == false
In 30.6.7 [future.shared_future], paragraph 5, shared_future(const shared_future&):
Change:
shared_future object that refers to the same
associated asynchronous state as rhs (if any).
In 30.6.7 [future.shared_future], paragraph 7, move-ctor shared_future:
Change:
shared_future object that refers to the
associated associated state that was originally referred to by
rhs (if any).
In 30.6.7 [future.shared_future], paragraph 10f, ~shared_future():
Change:
*this.
In 30.6.7 [future.shared_future], paragraph 12, move-assignment:
Change:
*this referred to an associated asynchronous
state prior to the assignment it gives up this reference.rhs to*this.
In 30.6.7 [future.shared_future], paragraph 14, copy-assignment:
Change:
*this referred to an associated asynchronous
state prior to the assignment it gives up this reference.rhs to*this.
[Note: So *this refers to the same associated
asynchronousstate as rhs
(if any). --end note]
In 30.6.7 [future.shared_future], paragraph 18ff, get():
Change:
wait()s until the associated asynchronous state
is ready.shared_future::get() returns a const reference to the value
stored in the object's associated asynchronous state.shared_future<R&>::get() returns the reference
stored as value in the object's associated asynchronous
state.future<void>::get() returns nothing.
In 30.6.7 [future.shared_future], paragraph 21, valid():
Change:
true only if *this refers to an associated
asynchronous state.
In 30.6.7 [future.shared_future], paragraph 22, wait():
Change:
valid() == true
In 30.6.7 [future.shared_future], paragraph 23ff, wait_for()/wait_until():
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
valid() == true
rel_time has elapsed.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time period specified
by rel_time has elapsed.template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
valid() == true
abs_time.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time point specified
by abs_time has been reached.
In 30.6.8 [futures.atomic_future], paragraph 1:
Change:
The class template atomic_future defines a type for
asynchronous return objects which may share their associated
asynchronous state with other asynchronous return objects.
A single atomic_future object may be shared between
different threads.
These objects can only be created by use of
A default-constructed promise ([future.promise])
or packaged_task ([future.task]) objects.atomic_future has no
associated asynchronous state. atomic_future
objects with associated asynchronous state can be created by
conversion from a future object
and share their associated asynchronous state with the original
asynchronous provider of the associated state.
Their values or exceptions can be set
by use of
The result (values or exceptions) of promise ([future.promise]) objects.atomic_future objects
can be set by calling a respective function on an object that
shares the same associated asynchronous state.
In 30.6.8 [futures.atomic_future], after paragraph 2, synopsis:
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
In 30.6.8 [futures.atomic_future], paragraph 3, atomic_future():
Change:
atomic_future that doesn't
refer to an associated asynchronous state.
In 30.6.8 [futures.atomic_future], before paragraph 5, atomic_future(const atomic_future&):
Change:
atomic_future object that refers to the same
associated asynchronous state as rhs (if any).
In 30.6.8 [futures.atomic_future], before paragraph 6, atomic_future(atomic_future<R>&& rhs):
Change:
atomic_future(atomic_future<R>&& rhs);
atomic_future object that refers to the
associated asynchronous state that was originally referred
to by rhs (if any).
In 30.6.8 [futures.atomic_future], after paragraph 6, ~atomic_future():
Change:
*this.
In 30.6.8 [futures.atomic_future], paragraph 7ff, operator=():
Change:
valid() == false
rhs to *this.
[Note: So *this refers to the same associated
asynchronous state as rhs (if any). --end note]
rhs and a release operation on *this.
In 30.6.8 [futures.atomic_future], paragraph 13ff, get():
Change:
valid() == true
wait()s until the associated asynchronous
state is ready.atomic_future::get() returns a const reference to the
value stored in the object's associated asynchronous state.atomic_future<R&>::get() returns the reference
stored as value in the object's associated asynchronous state.atomic_future<void>::get() returns nothing.future_error if an error condition occurs.
no_state if valid() == false.
future, calling get()
more than once on the same object is well defined and just produces
the result again. --end note]
In 30.6.8 [futures.atomic_future], paragraph 17, is_ready()ff:
Remove:
bool is_ready() const;
valid() == true
true only if the associated state is ready.
bool has_exception() const;
true only if the associated state is ready
and the associated state contains an exception.
bool has_value() const;
true only if the associated state is ready
and the associated state contains a value.
In 30.6.8 [futures.atomic_future], paragraph 22, wait():
Change:
future_error if an error condition occurs.
no_state — if *this has no
associated asynchronous state.
In 30.6.8 [futures.atomic_future], paragraph 23ff, wait_for()/wait_until():
Change:
template <class Rep, class Period>boolfuture_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
rel_time has elapsed.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time period specified
by rel_time has elapsed.future_error if an error condition occurs.
no_state if *this has no associated asynchronous
state.
template <class Clock, class Duration>boolfuture_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
abs_time.
true only if the associated state is ready.future_status::deferred if the associated
asynchronous state contains a deferred function that is not
running.future_status::ready if the associated
asynchronous state is ready.future_status::timeout if the function is
returning because the time point specified
by abs_time has been reached.future_error if an error condition occurs.
no_state if *this has no associated asynchronous
state.
In 30.6.9 [futures.async], just after the title:
Add:
async provides a mechanism to launch a function potentially
in a new thread and provides the result of the function in a
future object, with which it shares an associated
asynchronous state.
In 30.6.9 [futures.async] synopsis:
Change:
template <class F, class... Args>
future<typename F::result_typeresult_of<F(Args...)>::type>
async(F&& f, Args&&... args);
template <class F, class... Args>
future<typename F::result_typeresult_of<F(Args...)>::type>
async(launch policy, F&& f, Args&&... args);
In 30.6.9 [futures.async], paragraph 1, async():
Change:
F and each Ti in Args shall
CopyConstructible if an lvalue and otherwiseMoveConstructible requirements.
INVOKE(f, w1, w2, ..., wN) (20.7.2 [func.require]) shall be
a valid expression for some values w1, w2, ... , wN,
where N == sizeof...(Args).INVOKE(decay_copy(std::forward<F>(f)),
decay_copy(std::forward<Args>(args))...) (20.7.2 [func.require],
30.3.1.2 [thread.thread.constr]) shall be a valid expression."
future<typename F::result_type>.launch::any and the same arguments for
F and Args.
The second function creates an associated asynchronous state that is
associated with the returned future object.
The further behavior of the second function depends on the
policy argument as follows:
launch::async — executes
INVOKE (f, w1, w2, ..., wN)INVOKE(decay_copy(std::forward<F>(f)), decay_copy(std::forward<Args>(args))...)
as if in a new thread of execution represented by a thread object
with the calls to decay_copy() being evaluated in the
thread that called async.
Any return value is future objectfINVOKE(decay_copy(std::forward<F>(f)), decay_copy(std::forward<Args>(args))...)
is future objectfuture objectfuture objectfuture objects that reference that state.launch::sync
— INVOKE (f, w1, w2, ..., wN)
is associated with the future object.
The invocation is said to be deferred.decay_copy(std::forward<F>(f)) and
decay_copy(std::forward<Args>(args))... in the
associated asynchronous state. These copies of f and
args constitute a deferred function. Invocation of
the deferred function evaluates INVOKE(g,xyz) where
g is the stored value of
decay_copy(std::forward<F>(f)) and xyz
is the stored copy of
decay_copy(std::forward<Args>(args))...
The associated asynchronous state is not ready until the
function has completed.
The first call to a function waiting for the associated asynchronous
state created by this async() call to become ready
shall invoke the deferred function in the thread that called the
waiting function;
all other calls waiting for the same associated asynchronous state to
become ready shall block until the deferred function has completed.
launch::any — the implementation may choose either
async.
[Note: implementations should defer invocations when no more concurrency
can be effectively exploited. --end note ]future<typename result_of<F(Args...)>::type>
that refers to the associated asynchronous state created by this call to async.
async happens-before
([intro.multithread]) the invocation of f.
[Note: this statement applies even when the corresponding future
object is moved to another thread. --end note ]
async() call
shall block until the associated thread has completed.
join() on the created
thread happens-before [intro.multithread] the first function that successfully
detects the ready status of the associated asynchronous state returns
or before the function that gives up the last reference to the
associated asynchronous state returns, whichever happens first.
In 30.6.9 [futures.async], paragraph 5:
Change:
resource_unavailable_try_again — if policy
is launch::async and
In 30.6.9 [futures.async], after paragraph 5:
Add:
decay<F>::type is std::launch.
In 30.6.10 [futures.futures_task], paragraph 1, introduction:
Change:
A packaged_task provides a means of wrapping a
function or callable object so that the return value of the function
or callable object is stored in a future when it is invoked.
The associated state of a
packaged_task object includes
storage for a copy of this associated task.
When the packaged_task is invoked, its associated
stored task is invoked, and the result (whether normal or
exceptional) stored in the associated asynchronous state.
Any futures that shares the associated asynchronous state
will then be able to access the stored result.
In 30.6.10 [futures.futures_task], synopsis, after definition
of class template packaged_task:
Add:
template <class R, class... Argtypes>
void swap(packaged_task<R(ArgTypes...)>&, packaged_task<R(ArgTypes...)>&)
In 30.6.10 [futures.futures_task], paragraph 4, packaged_task():
Change:
packaged_task object with no
associated asynchronous state nor stored task.
In 30.6.10 [futures.futures_task], paragraph 6f, ctor:
Change:
INVOKE (f, t1, t2, ..., tN, R)
where t1, t2, ..., tN are
values of the corresponding types in ArgTypes....
shall be a valid expression. Invoking a copy of f
shall behave the same as invoking f.
packaged_task object and stores
f Allocator
argument use it to allocate memory needed to store the internal data
structures.
In 30.6.10 [futures.futures_task], paragraph 9f, move-ctor:
Change:
packaged_task
object and transfers other's stored task and
ownership of other's associated
asynchronous state to *this,
leaving other with no associated asynchronous state.
other has no associated asynchronous state.
In 30.6.10 [futures.futures_task], paragraph 13, ~packaged_task():
Change:
*this is
not ready, stores an exception of type future_error with an
error broken_promise.
Any threads blocked in a future, shared_future
or atomic_future*this to become ready are unblocked.
*this and the stored task, if any, and releases its
reference to its associated asynchronous state if any.
If this is the last reference to that associated asynchronous
state, destroys that state.
In 30.6.10 [futures.futures_task], paragraph 15f, swap():
Change:
*this and other.
*this has the same associated asynchronous state
and stored task (if any)
as other prior to the call
to swap. other has the same associated
asynchronous state and stored task (if any) as
*this prior to the call
to swap.
In 30.6.10 [futures.futures_task], paragraph 18, operator bool():
Change:
true if and only if *this has an associated
asynchronous state.
In 30.6.10 [futures.futures_task], paragraph 20ff, get_future():
Change:
future object that
shares the same associated asynchronous state as *this.
std::future_error if an error occurs.
future_already_retrieved if get_future
has already been called on
a packaged_task with the associated asynchronous
state of *this.no_state if *this has no associated
asynchronous state.
In 30.6.10 [futures.futures_task], paragraph 20ff, operator()():
Change:
INVOKE (f, t1, t2, ..., tN, R),
where f is the stored task *this and t1, t2,
..., tN are the values in args.... If
the task returns normally, the return value is stored as the
asynchronous result in the asynchronous state associated
with *this, otherwise the exception thrown by the
task is stored. The asynchronous state associated with
*this is
made ready, and any threads blocked in a future, shared_future
or atomic_future*this to become ready are
unblocked.
std::future_error if there is no
associated asynchrounous state or the stored task
has already been invoked.
no_state if *this has no associated
asynchronous state.promise_already_satisfied if the associated
asynchronous state is already ready.operator() synchronizes with
([intro.multithread]) a call to any member function of
a future object, shared_future
object or atomic_future object that shares the same
associated asynchronous state.
The completion of the invocation of the
operator() synchronizes and serializes with other functions
through the referred associated asynchronous state. --end note]
In 30.6.10 [futures.futures_task], paragraph 27f, reset():
Change:
*this by *this = packaged_task(std::move(f)),
where f is the task
stored in *this.
*this. The old state is discarded, as described in
the destructor
for packaged_task. get_future() may now be
called again for *this. -- end note]
std::bad_alloc if memory for the *this.std::future_error with an error condition
of no_state if *this has no
associated asynchronous state
In 30.6.10 [futures.futures_task], after paragraph 28 (at the end):
Add:
template <class R, class... Argtypes>
void swap(packaged_task<R(ArgTypes...)>& x, packaged_task<R(ArgTypes...)>& y)
x.swap(y)