home | help
std::async(3)		       C++ Standard Libary		   std::async(3)

NAME
     std::async - std::async

Synopsis
	Defined in header <future>
	template< class F, class... Args >
									     (since
	std::future<typename				 std::result_of<typename
     C++11)
	std::decay<F>::type(
     (until
		typename		      std::decay<Args>::type...)>::type>
     C++17)

	    async( F&& f, Args&&... args );
	template< class F, class... Args >
									     (since
	std::future<std::invoke_result_t<std::decay_t<F>,
     C++17)
					 std::decay_t<Args>...>>
     (until
									     C++20)
	    async( F&& f, Args&&... args );
	template< class F, class... Args >

	[[nodiscard]]
	std::future<std::invoke_result_t<std::decay_t<F>,
     (since
									     C++20)
	 std::decay_t<Args>...>>

	    async( F&& f, Args&&... args );			     (1)
	template< class F, class... Args >
										     (since
	std::future<typename				 std::result_of<typename
     C++11)
	std::decay<F>::type(
     (until
		typename		      std::decay<Args>::type...)>::type>
     C++17)

	    async( std::launch policy, F&& f, Args&&... args );
	template< class F, class... Args >
										     (since
	std::future<std::invoke_result_t<std::decay_t<F>,
     C++17)
					 std::decay_t<Args>...>>	     (2)
     (until
										     C++20)
	    async( std::launch policy, F&& f, Args&&... args );
	template< class F, class... Args >

	[[nodiscard]]
	std::future<std::invoke_result_t<std::decay_t<F>,
     (since
										     C++20)
	 std::decay_t<Args>...>>

	    async( std::launch policy, F&& f, Args&&... args );

	The function template std::async runs the function f asynchronously (po-
     tentially 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) Behaves as if (2) is called with policy being std::launch::async |
	std::launch::deferred.
	2) Calls a function f with arguments args according to a specific launch
     policy
	policy (see below).

	If any of the following conditions is satisfied, the program is
	ill-formed:

	  *	       F	   is		not	      MoveConstructible.
     (until C++20)
	  * Any type in Args is not MoveConstructible.
	  * INVOKE(decay-copy(std::forward<F>(f)),
		   decay-copy(std::forward<Args>(args))...) is not a valid
	    expression.
	If any of the following is false, the program is ill-formed:

	  *		std::is_constructible_v<std::decay_t<F>,	      F>
     (since C++20)
	  * (std::is_constructible_v<std::decay_t<Args>, Args> && ...)
	  * std::is_invocable_v<std::decay_t<F>, std::decay_t<Args>...>

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

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

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

	Launch policies

	  Async invocation

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

	std::async calls INVOKE(decay-copy(std::forward<F>(f)),
	       decay-copy(std::forward<Args>(args))...) as if in  a  new  thread
     (until C++23)
	of execution represented by a std::thread object.
	std::async calls std::invoke(auto(std::forward<F>(f)),
		    auto(std::forward<Args>(args))...)	as  if	in  a new thread
     (since C++23)
	of execution represented by a std::thread object.

	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.

	  Deferred invocation

	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::for-
     ward<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:

	  * The first call to a non-timed wait function on the 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).
	  * The result or exception is placed in  the  shared  state  associated
     with the
	    returned std::future and only then it is made ready. All further ac-
     cesses to the
	    same std::future will return the result immediately.

	  Other policies

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

	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 avail-
     able
	concurrency, and deferring any additional tasks.

	If the std::launch::async policy is chosen,

	  * a call to a waiting function on an asynchronous return  object  that
     shares the
	    shared  state created by this std::async call blocks until the asso-
     ciated thread
	    has completed, as if joined, or else time out; and
	  * the associated thread completion  synchronizes-with  the  successful
     return from
	    the  first function that is waiting on the shared state, or with the
     return of
	    the last function that releases the shared	state,	whichever  comes
     first.

Exceptions
	Throws

	  *  std::bad_alloc, if the memory for the internal data structures can-
     not 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.
	       *  If 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.

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 mak-
     ing 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::futures obtained by means other than a
     call to
	std::async never block.

Example
     // Run this code

      #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

	Defect reports

	The following behavior-changing defect	reports  were  applied	retroac-
     tively to
	previously published C++ standards.

	   DR	  Applied  to	      Behavior as published		 Correct
     behavior
			    return type incorrect and value	  corrected  re-
     turn type and
	LWG 2021 C++11	    category				  clarified that
     rvalues are
			    of arguments unclear in the deferred  used
			    case
			    it was unclear whether
			    std::system_error			   can	only  be
     thrown if
	LWG 2078 C++11	    may be thrown if policy specifies	  policy ==
			    other
     std::launch::async
			    launch policies besides
			    std::launch::async
			    timed waiting functions could not
	LWG 2100 C++11	    timeout				  allowed
			    if std::launch::async policy is used
			    the behavior was unclear if no
	LWG 2120 C++11	    standard				   the	behavior
     is
			    or	implementation-defined	policy is   undefined in
     this case
			    set
			    std::async might not throw
	LWG 2752 C++11	    std::bad_alloc if the		  throws
			    memory for the internal data
			    structures cannot be allocated
			    (the decayed types of) F and the
	LWG 3476 C++20	    argument types			  removed these
			    were  directly  required  to  be  move	require-
     ments^[1]
			    constructible

	 1. a The move-constructibility is already indirectly required by
	    std::is_constructible_v.

See also
	future	waits for a value that is set asynchronously
	(C++11) (class template)

http://cppreference.com 	   2024.06.10			   std::async(3)

home | help