std::async - cppreference.com (original) (raw)

Defined in header
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, F&& f, Args&&... args ); (2) (since C++11)

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.

  1. Calls a function f with arguments args according to a specific launch policy policy (see below).

The return type of std::async is std::future<V>, where V is:

The call to std::async synchronizes with the call to f, and the completion of f is sequenced before making the shared state ready.

Contents

[edit] Parameters

f - Callable object to call
args - parameters to pass to f
policy - bitmask value, where individual bits control the allowed methods of execution

[edit] Return value

std::future referring to the shared state created by this call to std::async.

[edit] Launch policies

[edit] Async invocation

If the async flag is set, i.e. (policy & std::launch::async) != 0, then std::async calls

as if in a new thread of execution represented by a std::thread object.

The calls of decay-copy are evaluated in the current thread. (until C++23)
The values produced by auto are materialized in the current thread. (since C++23)

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.

[edit] Deferred invocation

If the deferred flag is set (i.e. (policy & std::launch::deferred) != 0), then std::async stores

Lazy evaluation is performed:

[edit] Other policies

If neither std::launch::async nor std::launch::deferred, nor any implementation-defined policy flag is set in policy, the behavior is undefined.

[edit] Policy selection

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,

[edit] Exceptions

Throws

[edit] Notes

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:

Note that the destructors of std::futures obtained by means other than a call to std::async never block.

[edit] Example

#include #include #include #include #include #include #include   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 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, mid, end); int sum = parallel_sum(beg, mid); return sum + handle.get(); }   int main() { std::vector 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

[edit] Defect reports

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 categoryof arguments unclear in the deferred case corrected return type andclarified that rvalues are used
LWG 2078 C++11 it was unclear whether std::system_errormay 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 timeoutif std::launch::async policy is used allowed
LWG 2120 C++11 the behavior was unclear if no standardor implementation-defined policy is set the behavior isundefined in this case
LWG 2186 C++11 it was unclear how the value returned and theexception thrown from the lazy evaluation are handled they are stored inthe shared state
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++20 (the decayed types of) F and the argument typeswere directly required to be move constructible removed these requirements[1]
  1. The move-constructibility is already indirectly required by std::is_constructible_v.

[edit] See also