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:
constexprerror_code make_error_code(future_errc e);constexprerror_condition make_error_condition(future_errc e);externconst 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<typenameF::result_typeresult_of<F(Args...)>::type> async(F&& f, Args&&... args); template <class F, class... Args> future<typenameF::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<typenameF::result_typeresult_of<F(Args...)>::type> async(F&& f, Args&&... args); template <class F, class... Args> future<typenameF::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
objectf
INVOKE(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)