std::async - cppreference

std::async - cppreference

1. std::async

Defined in header <future>

async (C++11)
runs a function asynchronously (potentially in a new thread) and returns a std::future that will hold the result (function template)。
异步运行一个函数 (有可能在新线程中执行),并返回保有其结果的 std::future (函数模板)。

potentially [pəˈtenʃəli]:adv. 可能地,潜在地
header [ˈhedə(r)]:n. 头球,页眉,数据头,收割台

1.1 since C++11 - until C++17

template <class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
async( Function&& f, Args&&... args );

1.2 since C++17 - until C++20

template <class Function, class... Args>
std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>>
async( Function&& f, Args&&... args );

1.3 since 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 );

1.4 since C++11 - until C++17

template <class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
async( std::launch policy, Function&& f, Args&&... args );

1.5 since C++17 - until C++20

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 );

1.6 since 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 );

defer [dɪˈfɜː(r)]:vi. 推迟,延期,服从 vt. 使推迟,使延期
asynchronous [eɪˈsɪŋkrənəs]:adj. 异步的,不同时的,不同期的

The template function async runs the function f asynchronously (potentially in a separate thread which may be part of a thread pool) and returns a std::future that will eventually hold the result of that function call.
模板函数 async 异步地运行函数 f (潜在地在可能是线程池一部分的分离线程中),并返回最终将保有该函数调用结果的 std::future

  1. Behaves as if (2) is called with policy being std::launch::async | std::launch::deferred. In other words, f may be executed in another thread or it may be run synchronously when the resulting std::future is queried for a value.
    表现如同以 policystd::launch::async | std::launch::deferred 调用 (2)。换言之,f 可能执行于另一线程,或者它可能在查询产生的 std::future 的值时同步运行。

  2. Calls a function f with arguments args according to a specific launch policy policy:
    按照特定的执行策略 policy,以参数 args 调用函数 f

If the async flag is set (i.e. (policy & std::launch::async) != 0), then async executes the callable object f on a new thread of execution (with all thread-locals initialized) as if spawned by std::thread(std::forward<F>(f), std::forward<Args>(args)...), except that if the function f returns a value or throws an exception, it is stored in the shared state accessible through the std::future that async returns to the caller.
若设置 async 标志 (即 (policy & std::launch::async) != 0),则 async 在新的执行线程 (初始化所有线程局域对象后) 执行可调用对象 f,如同产出 std::thread(std::forward<F>(f), std::forward<Args>(args)...),除了若 f 返回值或抛出异常,则于可通过 async 返回给调用方的 std::future 访问的共享状态存储结果。

If the deferred flag is set (i.e. (policy & std::launch::deferred) != 0), then async converts f and args... the same way as by std::thread constructor, but does not spawn a new thread of execution. Instead, lazy evaluation is performed: the first call to a non-timed wait function on the std::future that async returned to the caller will cause the copy of f to be invoked (as an rvalue) with the copies of args... (also passed as rvalues) in the current thread (which does not have to be the thread that originally called std::async). The result or exception is placed in the shared state associated with the future and only then it is made ready. All further accesses to the same std::future will return the result immediately.
若设置 deferred 标志 (即 (policy & std::launch::deferred) != 0)),则 async 以同 std::thread 构造函数的方式转换 fargs...,但不产出新的执行线程。而是进行惰性求值:在 async 所返回的 std::future 上首次调用非定时等待函数,将导致在当前线程 (不必是最初调用 std::async 的线程) 中,以 args... (作为右值传递) 的副本调用 f (亦作为右值) 的副本。将结果或异常置于关联到该 future 的共享状态,然后才令它就绪。对同一 std::future 的所有后续访问都会立即返回结果。

If both the std::launch::async and std::launch::deferred flags are set in policy, it is up to the implementation whether to perform asynchronous execution or lazy evaluation.
policy 中设置了 std::launch::asyncstd::launch::deferred 两个标志,则进行异步执行还是惰性求值取决于实现。

If neither std::launch::async nor std::launch::deferred, nor any implementation-defined policy flag is set in policy, the behavior is undefined. (since C++14)
policy 中未设置 std::launch::asyncstd::launch::deferred 或任何实现定义策略标志,则行为未定义。

In any case, 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 the async policy is chosen, 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.
任何情况下,对 std::async 的调用同步于 (定义于 std::memory_order) 对 f 的调用,且 f 的完成先序于令共享状态就绪。若选择 async 策略,则关联线程的完成同步于首个等待于共享状态上的函数的成功返回,或最后一个释放共享状态的函数的返回,两者的先到来者。

2. Parameters - 参数

f - Callable object to call (要调用的可调用 (callable) 对象)
args... - parameters to pass to f (传递给 f 的参数)
policy - bitmask value, where individual bits control the allowed methods of execution (位掩码值,每个单独位控制允许的执行方法)

Bit (位) - Explanation (解释)
std::launch::async - enable asynchronous evaluation (启用异步求值)
std::launch::deferred - enable lazy evaluation (启用惰性求值)

async [əˈsɪŋk]:abbr. 异步,非同步 (asynchronous)

2.1 Type requirements - 类型要求

Function, Args must meet the requirements of MoveConstructible.
Function, Args 必须满足可移动构造 (MoveConstructible) 的要求。

3. Return value - 返回值

std::future referring to the shared state created by this call to std::async.
指代此次调用 std::async 所创建的共享状态的 std::future

4. Exceptions

Throws std::system_error with error condition std::errc::resource_unavailable_try_again if the launch policy equals std::launch::async and the implementation is unable to start a new thread (if the policy is async|deferred or has additional bits set, it will fall back to deferred or the implementation-defined policies in this case), or std::bad_alloc if memory for the internal data structures could not be allocated.
若运行策略等于 std::launch::async 且实现无法开始新线程 (该情况下,若运行策略为 async|deferred 或设置了额外位,则它将回退到 deferred 或实现定义的策略),则抛出以 std::errc::resource_unavailable_try_again 为错误条件的 std::system_error,或者若无法分配内部数据结构所用的内存,则为 std::bad_alloc

5. 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.
实现可以通过在默认运行策略中启用额外 (实现定义的) 位,扩展 std::async 第一重载的行为。

Examples of implementation-defined launch policies are the sync policy (execute immediately, within the async call) and the task policy (similar to async, but thread-locals are not cleared)
实现定义的运行策略的例子是同步策略 (在 async 调用内立即执行) 和任务策略 (类似 async,但不清理线程局域对象)。

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::future 未被移动或绑定到引用,则在完整表达式结尾,std::future 的析构函数将阻塞直至异步计算完成,实质上令如下代码同步:

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f() - 临时量的析构函数等待 f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes - f() 完成前不开始

(note that the destructors of std::futures obtained by means other than a call to std::async never block)
(注意,以调用 std::async 以外的方式获得的 std::future 的析构函数决不阻塞)

6. Defect reports - 缺陷报告

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

retroactively [ˌretroʊˈæktɪvli]:adv. 追溯地,逆动地

7. Example

//============================================================================
// Name        : std::async
// Author      : Yongqiang Cheng
// Version     : Version 1.0.0
// Copyright   : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <string>
#include <mutex>

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"

	return 0;
} // if a1 is not done at this point, destructor of a1 prints "Hello 42" here

22:18:58 **** Build of configuration Debug for project hello_world ****
make all 
Building file: ../src/hello_world.cpp
Invoking: GCC C++ Compiler
g++ -std=c++1y -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/hello_world.d" -MT"src/hello_world.o" -o "src/hello_world.o" "../src/hello_world.cpp"
Finished building: ../src/hello_world.cpp
 
Building target: hello_world
Invoking: GCC C++ Linker
g++  -o "hello_world"  ./src/hello_world.o   
./src/hello_world.o: In function `std::thread::thread<std::__future_base::_Async_state_impl<std::_Bind_simple<std::_Mem_fn<void (X::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X, char const*)>, void>::_Async_state_impl(std::_Bind_simple<std::_Mem_fn<void (X::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X, char const*)>&&)::{lambda()#1}>(std::__future_base::_Async_state_impl<std::_Bind_simple<std::_Mem_fn<void (X::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X, char const*)>, void>::_Async_state_impl(std::_Bind_simple<std::_Mem_fn<void (X::*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X, char const*)>&&)::{lambda()#1}&&)':
/usr/include/c++/5/thread:137: undefined reference to `pthread_create'
./src/hello_world.o: In function `std::thread::thread<std::__future_base::_Async_state_impl<std::_Bind_simple<X (int)>, int>::_Async_state_impl(std::_Bind_simple<X (int)>&&)::{lambda()#1}>(std::__future_base::_Async_state_impl<std::_Bind_simple<X (int)>, int>::_Async_state_impl(std::_Bind_simple<X (int)>&&)::{lambda()#1}&&)':
/usr/include/c++/5/thread:137: undefined reference to `pthread_create'
./src/hello_world.o: In function `std::thread::thread<std::__future_base::_Async_state_impl<std::_Bind_simple<int (*(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >))(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >)>, int>::_Async_state_impl(std::_Bind_simple<int (*(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >))(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >)>&&)::{lambda()#1}>(std::__future_base::_Async_state_impl<std::_Bind_simple<int (*(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >))(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >)>, int>::_Async_state_impl(std::_Bind_simple<int (*(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >))(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >)>&&)::{lambda()#1}&&)':
makefile:45: recipe for target 'hello_world' failed
/usr/include/c++/5/thread:137: undefined reference to `pthread_create'
./src/hello_world.o: In function `std::thread::thread<std::__future_base::_Async_state_impl<std::_Bind_simple<std::_Mem_fn<void (X::*)(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X*, int, char const*)>, void>::_Async_state_impl(std::_Bind_simple<std::_Mem_fn<void (X::*)(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X*, int, char const*)>&&)::{lambda()#1}>(std::__future_base::_Async_state_impl<std::_Bind_simple<std::_Mem_fn<void (X::*)(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X*, int, char const*)>, void>::_Async_state_impl(std::_Bind_simple<std::_Mem_fn<void (X::*)(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> (X*, int, char const*)>&&)::{lambda()#1}&&)':
/usr/include/c++/5/thread:137: undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status
make: *** [hello_world] Error 1

22:19:00 Build Finished (took 2s.274ms)

undefined reference to pthread_create
Project -> properties -> C/C++ Build -> Settings -> Tool Settings -> GCC C++ Linker -> Libraries (-l) 添加 pthread 参数。

在这里插入图片描述

Possible output

The sum is 10000
world!
43
53

References

https://en.cppreference.com/w/cpp/thread/async

发布了454 篇原创文章 · 获赞 1733 · 访问量 103万+

猜你喜欢

转载自blog.csdn.net/chengyq116/article/details/104419324