|
|
Defined in header <future> | ||
template<class F,class...Args> std::future</* see below */> async( F&& f, Args&&...args); | (1) | (since C++11) |
template<class F,class...Args> std::future</* see below */> async(std::launch policy, | (2) | (since C++11) |
The function templatestd::async
runs the functionf asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns astd::future that will eventually hold the result of that function call.
The return type ofstd::async
isstd::future<V>, whereV
is:
typenamestd::result_of<typenamestd::decay<F>::type( | (until C++17) |
std::invoke_result_t<std::decay_t<F>,std::decay_t<Args>...>. | (since C++17) |
If any of the following conditions is satisfied, the program is ill-formed:
| (until C++20) |
If any of the following isfalse, the program is ill-formed:
| (since C++20) |
The call tostd::async
synchronizes with the call tof, and the completion off issequenced before making the shared state ready.
Contents |
f | - | Callable object to call |
args | - | parameters to pass tof |
policy | - | bitmask value, where individual bits control the allowed methods of execution |
std::future referring to the shared state created by this call tostd::async
.
If theasync flag is set, i.e.(policy&std::launch::async)!=0, thenstd::async
calls
INVOKE(decay-copy(std::forward<F>(f)), | (until C++23) |
std::invoke(auto(std::forward<F>(f)), | (since C++23) |
as if in a new thread of execution represented by astd::thread object.
The calls ofdecay-copy are evaluated in the current thread. | (until C++23) |
The values produced byauto arematerialized in the current thread. | (since C++23) |
If the functionf returns a value or throws an exception, it is stored in the shared state accessible through thestd::future thatstd::async
returns to the caller.
If thedeferred flag is set (i.e.(policy&std::launch::deferred)!=0), thenstd::async
stores
decay-copy(std::forward<F>(f)) anddecay-copy(std::forward<Args>(args))... in the shared state. | (until C++23) |
auto(std::forward<F>(f)) andauto(std::forward<Args>(args))... in the shared state. | (since C++23) |
Lazy evaluation is performed:
std::async
returned to the caller will evaluateINVOKE(std::move(g), std::move(xyz)) in the thread that called the waiting function (which does not have to be the thread that originally calledstd::async
), where
| (until C++23) |
| (since C++23) |
If neitherstd::launch::async norstd::launch::deferred, nor any implementation-defined policy flag is set inpolicy, the behavior is undefined.
If more than one flag is set, it is implementation-defined which policy is selected. For the default (both thestd::launch::async andstd::launch::deferred flags are set inpolicy), standard recommends (but does not require) utilizing available concurrency, and deferring any additional tasks.
If thestd::launch::async policy is chosen,
std::async
call blocks until the associated thread has completed, as if joined, or else time out; andThrows
The implementation may extend the behavior of the first overload ofstd::async
by enabling additional (implementation-defined) bits in the default launch policy.
Examples of implementation-defined launch policies are the sync policy (execute immediately, within thestd::async
call) and the task policy (similar tostd::async
, but thread-locals are not cleared)
If thestd::future obtained fromstd::async
is not moved from or bound to a reference, the destructor of thestd::future will block at the end of the full expression until the asynchronous operation completes, essentially making code such as the following synchronous:
std::async(std::launch::async,[]{ f();});// temporary's dtor waits for f()std::async(std::launch::async,[]{ g();});// does not start until f() completes
Note that the destructors ofstd::futures obtained by means other than a call tostd::async
never block.
#include <algorithm>#include <future>#include <iostream>#include <mutex>#include <numeric>#include <string>#include <vector> std::mutex m; struct X{void foo(int i,conststd::string& str){std::lock_guard<std::mutex> lk(m);std::cout<< str<<' '<< i<<'\n';} void bar(conststd::string& str){std::lock_guard<std::mutex> lk(m);std::cout<< str<<'\n';} int operator()(int i){std::lock_guard<std::mutex> lk(m);std::cout<< i<<'\n';return i+10;}}; template<typename RandomIt>int parallel_sum(RandomIt beg, RandomIt end){auto len= end- beg;if(len<1000)returnstd::accumulate(beg, end,0); RandomIt mid= beg+ len/2;auto handle= std::async(std::launch::async, parallel_sum<RandomIt>, mid, end);int sum= parallel_sum(beg, mid);return sum+ handle.get();} int main(){std::vector<int> v(10000,1);std::cout<<"The sum is "<< parallel_sum(v.begin(), v.end())<<'\n'; X x;// Calls (&x)->foo(42, "Hello") with default policy:// may print "Hello 42" concurrently or defer executionauto a1= std::async(&X::foo,&x,42,"Hello");// Calls x.bar("world!") with deferred policy// prints "world!" when a2.get() or a2.wait() is calledauto a2= std::async(std::launch::deferred,&X::bar, x,"world!");// Calls X()(43); with async policy// prints "43" concurrentlyauto a3= std::async(std::launch::async, X(),43); a2.wait();// prints "world!"std::cout<< a3.get()<<'\n';// prints "53"}// if a1 is not done at this point, destructor of a1 prints "Hello 42" here
Possible output:
The sum is 1000043world!53Hello 42
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 2021 | C++11 | return type incorrect and value category of arguments unclear in the deferred case | corrected return type and clarified that rvalues are used |
LWG 2078 | C++11 | it was unclear whetherstd::system_error may be thrown ifpolicy specifies other launch policies besidesstd::launch::async | can only be thrown if policy==std::launch::async |
LWG 2100 | C++11 | timed waiting functions could not timeout ifstd::launch::async policy is used | allowed |
LWG 2120 | C++11 | the behavior was unclear if no standard or implementation-defined policy is set | the behavior is undefined in this case |
LWG 2186 | C++11 | it was unclear how the value returned and the exception thrown from the lazy evaluation are handled | they are stored in the shared state |
LWG 2752 | C++11 | std::async might not throwstd::bad_alloc if thememory for the internal data structures cannot be allocated | throws |
LWG 3476 | C++20 | (the decayed types of)F and the argument typeswere directly required to be move constructible | removed these requirements[1] |
(C++11) | waits for a value that is set asynchronously (class template)[edit] |
C++ documentation forExecution support library |