Defined in header <future> | ||
---|---|---|
(1) | ||
template< class Function, class... Args > std::future<typename std::result_of<typename std::decay<Function>::type( typename std::decay<Args>::type...)>::type> async( Function&& f, Args&&... args ); | (since C++11) (until C++17) | |
template< class Function, class... Args > std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>> async( Function&& f, Args&&... args ); | (since C++17) (until C++20) | |
template< class Function, class... Args > [[nodiscard]] std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>> async( Function&& f, Args&&... args ); | (since C++20) | |
(2) | ||
template< class Function, class... Args > std::future<typename std::result_of<typename std::decay<Function>::type( typename std::decay<Args>::type...)>::type> async( std::launch policy, Function&& f, Args&&... args ); | (since C++11) (until C++17) | |
template< class Function, class... Args > std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>> async( std::launch policy, Function&& f, Args&&... args ); | (since C++17) (until C++20) | |
template< class Function, class... Args > [[nodiscard]] std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>> async( std::launch policy, Function&& f, Args&&... args ); | (since C++20) |
The function template std::async
runs the function f
asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future
that will eventually hold the result of that function call.
The call to std::async
synchronizes-with (as defined in std::memory_order
) the call to f
, and the completion of f
is sequenced-before making the shared state ready.
If | (until C++20) |
The program is ill-formed if.
| (since C++20) |
f | - | Callable object to call | ||||||
args... | - | parameters to pass to f |
||||||
policy | - | bitmask value, where individual bits control the allowed methods of execution
|
std::future
referring to the shared state created by this call to std::async
.
If the async flag is set (i.e. (policy & std::launch::async) != 0
), then.
| (until C++23) |
| (since C++23) |
The calls of decay-copy
are evaluated (until C++23)The values produced by auto
are materialized (since C++23) in the current thread. If the function f
returns a value or throws an exception, it is stored in the shared state accessible through the std::future
that std::async
returns to the caller.
If the deferred flag is set (i.e. (policy & std::launch::deferred) != 0
), then std::async
stores decay-copy(std::forward<F>(f))
and decay-copy(std::forward<Args>(args))...
(until C++23)auto(std::forward<F>(f))
and auto(std::forward<Args>(args))...
(since C++23) in the shared state.
Lazy evaluation is performed:
std::future
that std::async
returned to the caller will evaluate INVOKE(std::move(g), std::move(xyz))
in the current thread (which does not have to be the thread that originally called std::async
), where g
is the stored value of decay-copy(std::forward<F>(f))
(until C++23)auto(std::forward<F>(f))
(since C++23) and xyz
is the stored copy of decay-copy(std::forward<Args>(args))...
(until C++23)auto(std::forward<Args>(args))...
(since C++23). std::future
and only then it is made ready. All further accesses to the same std::future
will return the result immediately. If neither std::launch::async
nor std::launch::deferred
, nor any implementation-defined policy flag is set in policy
, the behavior is undefined.
If more than one flag is set, it is implementation-defined which policy is selected. For the default (both the std::launch::async
and std::launch::deferred
flags are set in policy
), standard recommends (but does not require) utilizing available concurrency, and deferring any additional tasks.
If the std::launch::async
policy is chosen,
std::async
call blocks until the associated thread has completed, as if joined, or else time out; and Throws.
std::bad_alloc
, if the memory for the internal data structures cannot be allocated, or std::system_error
with error condition std::errc::resource_unavailable_try_again
, if policy == std::launch::async
and the implementation is unable to start a new thread. policy
is std::launch::async | std::launch::deferred
or has additional bits set, it will fall back to deferred invocation or the implementation-defined policies in this case. The implementation may extend the behavior of the first overload of std::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 the std::async
call) and the task policy (similar to std::async
, but thread-locals are not cleared).
If the std::future
obtained from std::async
is not moved from or bound to a reference, the destructor of the std::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 of std::future
s obtained by means other than a call to std::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, const std::string& str) { std::lock_guard<std::mutex> lk(m); std::cout << str << ' ' << i << '\n'; } void bar(const std::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) return std::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 execution auto a1 = std::async(&X::foo, &x, 42, "Hello"); // Calls x.bar("world!") with deferred policy // prints "world!" when a2.get() or a2.wait() is called auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!"); // Calls X()(43); with async policy // prints "43" concurrently auto 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 10000 43 world! 53 Hello 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 whether std::system_error may be thrown if policy specifies otherlaunch policies besides std::launch::async | can only be thrown ifpolicy == std::launch::async |
LWG 2100 | C++11 | timed waiting functions could not timeout if std::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 2752 | C++11 | std::async might not throw std::bad_alloc if thememory for the internal data structures cannot be allocated | throws |
LWG 3476 | C++11 | Function and Args... were required to be MoveConstructiblewhile no additional move constructions specified | requirements removed |
(C++11) | waits for a value that is set asynchronously (class template) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/async