| 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() completesNote that the destructors of std::futures 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" herePossible 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_errormay be thrown if policyspecifies otherlaunch policies besides std::launch::async | can only be thrown if policy == std::launch::async | 
| LWG 2100 | C++11 | timed waiting functions could not timeout if std::launch::asyncpolicy 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::asyncmight not throwstd::bad_allocif thememory for the internal data structures cannot be allocated | throws | 
| LWG 3476 | C++11 | FunctionandArgs...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