std::async - cplusplus

std::async - cplusplus

function template - <future>

1. std::async

unspecified policy (1)
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type>
async (Fn&& fn, Args&&... args);

specific policy (2)
template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type>
async (launch policy, Fn&& fn, Args&&... args);

Call function asynchronously - 异步调用函数

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. 可能地,潜在地

Calls fn (with args as arguments) at some point, returning without waiting for the execution of fn to complete.
在某个时候调用 fn (以 args 为参数),返回时不等待 fn 的执行完成。

The value returned by fn can be accessed through the future object returned (by calling its member future::get).
fn 返回的值可以通过返回的 future 对象来访问 (通过调用其成员 future::get)。

The second version (2) lets the caller select a specific launching policy, while the first version (1) uses automatic selection, as if calling (2) with launch::async|launch::deferred as policy.
第二个版本 (2) 允许调用者选择特定的启动策略,而第一个版本 (1) 使用自动选择,就像使用 (launch::async|launch::deferred) 作为 policy 来调用 (2) 一样。

The function temporarily stores in the shared state either the threading handler used or decay copies of fn and args (as a deferred function) without making it ready. Once the execution of fn is completed, the shared state contains the value returned by fn and is made ready.
该函数在共享状态下临时存储使用的线程处理程序或 fnargsdecay copies (作为延迟函数),而不使其准备就绪。一旦执行完 fn,共享状态将包含 fn 返回的值,并使其准备就绪。

conform [kənˈfɔːm]:vi. 符合,遵照,适应环境 vt. 使遵守,使一致,使顺从 adj. 一致的,顺从的
dereference [ˌdiːˈrefrəns]:v.	 间接引用,间接访问,解引用
reallocate [ˌriːˈæləkeɪt]:v. 重新分配,再指派

2. Parameters

policy
A bitmask value of type launch indicating the launching policy:
启动类型的位掩码值,指示启动策略:

launch::async
Asynchronous: Launches a new thread to call fn (as if a thread object is constructed with fn and args as arguments, and accessing the shared state of the returned future joins it).
异步:启动一个新线程来调用 fn (就像一个线程对象是用 fnargs 作为参数构造的,并访问返回的 future 的共享状态将其加入)。

launch::deferred
Deferred: The call to fn is deferred until the shared state of the returned future is accessed (with wait or get). At that point, fn is called and the function is no longer considered deferred. When this call returns, the shared state of the returned future is made ready.
Deferred: 延迟对 fn 的调用,直到访问返回的 future 的共享状态 (使用 waitget)。此时,将调用 fn,并且不再认为该函数是延迟的。当此调用返回时,返回的 future 的共享状态已准备就绪。

launch::async|launch::deferred
Automatic: The function chooses the policy automatically (at some point). This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.
自动:该功能自动选择策略 (在某些时候)。这取决于系统和库的实现,它们通常会针对系统中当前的并发可用性进行优化。

policy description
launch::async Asynchronous: Launches a new thread to call fn (as if a thread object is constructed with fn and args as arguments, and accessing the shared state of the returned future joins it).
launch::deferred Deferred: The call to fn is deferred until the shared state of the returned future is accessed (with wait or get). At that point, fn is called and the function is no longer considered deferred. When this call returns, the shared state of the returned future is made ready.
launch::async|launch::deferred Automatic: The function chooses the policy automatically (at some point). This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.

Particular library implementations may support additional launching policies, with the proper label defined in type launch. Combining multiple values is possible, in which case, the function automatically chooses one among them.
特定的库实现可能支持附加的启动策略,并在类型启动中定义适当的标签。可以组合多个值,在这种情况下,该功能会自动在其中选择一个。

fn
A pointer to function, pointer to member, or any kind of move-constructible function object (i.e., an object whose class defines operator(), including closures and function objects).
指向函数的指针,指向成员的指针或任何类型的可移动构造的函数对象 (即,其类定义了 operator() 的对象,包括闭包和函数对象)。

closure [ˈkləʊʒə(r)]:n. 关闭,终止,结束 vt. 使终止

The function uses a decay copy of this argument.
该函数使用此参数的 decay copy

The return value of fn is stored as the shared state to be retrieved by the future object returned by async.
fn 的返回值存储为共享状态,以供异步返回的 future 对象检索。

If fn throws, the exception is set in the shared state to be retrieved by the future object.
如果 fn 抛出,则将异常设置为共享状态,以供 future 对象检索。

args...
Arguments passed to the call to fn (if any). Their types shall be move-constructible.
传递给 fn 调用的参数 (如果有)。它们的类型应是可移动构造的。

If fn is a member pointer, the first argument shall be an object for which that member is defined (or a reference, or a pointer to it).
如果 fn 是成员指针,则第一个参数应是为其定义了该成员的对象 (或其引用或指向它的指针)。

The function uses decay copies of these arguments.
该函数使用这些参数的 decay copies

Fn and Args... are template parameters: if implicitly deduced, these are the proper lvalue or rvalue reference types of the arguments. Note though, that the function uses decay copies of fn and args... (see std::ref for a wrapper class that makes references copyable).
FnArgs ... 是模板参数:如果隐式推导,则它们是参数的正确左值或右值引用类型。不过请注意,该函数使用 fnargs... 的衰变副本 (有关使引用可复制的包装器类,请参见 std::ref)。

3. Return value

A future object whose shared state is made ready when the execution of fn ends. The value retrieved by its member future::get is the value returned by fn (if any).
fn 执行结束时,共享对象已准备就绪的 future 对象。由其成员 future::get 检索的值是 fn (如果有) 返回的值。

When launch::async is selected, the future returned is linked to the end of the thread created, even if its shared state is never accessed: in this case, its destructor synchronizes with the return of fn. Therefore, the return value shall not be disregarded for asynchronous behavior, even when fn returns void.
当选择 launch::async 时,返回的 future 链接到创建的线程的末尾,即使它的共享状态从未被访问过:在这种情况下,它的析构函数与 fn 的返回同步。因此,即使fn 返回 void,异步行为也不应忽略该返回值。

result_of::type is the type returned by Fn when called with arguments of the types in Args.
result_of::typeFn 返回的类型,当使用 Args 中的类型的参数调用时。

4. Examples

4.1 std::async - launch::async|launch::deferred

//============================================================================
// 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>       // std::cout
#include <future>         // std::async, std::future

// a non-optimized way of checking for prime numbers:
bool is_prime(int x)
{
	std::cout << "Calculating. Please, wait...\n";
	for (int i = 2; i < x; ++i)
	{
		if (x % i == 0)
		{
			return false;
		}
	}

	return true;
}

int main()
{
	// call is_prime(313222313) asynchronously:
	std::future<bool> fut = std::async(is_prime, 313222313);

	std::cout << "Checking whether 313222313 is prime.\n";

	bool ret = fut.get();      // waits for is_prime to return

	if (ret)
	{
		std::cout << "It is prime!\n";
	}
	else
	{
		std::cout << "It is not prime.\n";
	}

	return 0;
}

Possible output (the first two lines may be in a different order, or scrambled):
可能的输出 (前两行可能是不同的顺序,或者是 scrambled):

00:46:16 **** Build of configuration Debug for project hello_world ****
make all 
Building file: ../src/hello_world.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -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   -lpthread
Finished building target: hello_world
 

00:46:17 Build Finished (took 1s.280ms)
scramble ['skræmb(ə)l]:n. 争夺,争抢,爬,抢占 v. 争夺,争抢,(迅速而吃力地) 爬,抢占
Checking whether 313222313 is prime.
Calculating. Please, wait...
It is prime!

4.2 std::async - launch::async|launch::deferred

//============================================================================
// 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>       // std::cout
#include <future>         // std::async, std::future

using namespace std;

void print_task()
{
	for (int i = 0; i < 16; i++)
	{
		cout << "yong ";
	}
}

int main()
{
	future<void> ret = async(print_task);

	cout << "forever" << endl;

	for (int i = 0; i < 16; i++)
	{
		cout << "qiang ";
	}

	cout << "\nstrong" << endl;

	ret.get();

	return 0;
}


01:06:44 **** Build of configuration Debug for project hello_world ****
make all 
Building file: ../src/hello_world.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -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   -lpthread
Finished building target: hello_world
 

01:06:45 Build Finished (took 1s.381ms)
forever
qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang 
strong
yong yong yong yong yong yong yong yong yong yong yong yong yong yong yong yong 

4.3 std::async - launch::async

//============================================================================
// 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>       // std::cout
#include <future>         // std::async, std::future

using namespace std;

void print_task()
{
	for (int i = 0; i < 6; i++)
	{
		cout << "yong ";
	}
}

int main()
{
	future<void> ret = async(launch::async, print_task);

	cout << "forever" << endl;

	for (int i = 0; i < 16; i++)
	{
		cout << "qiang ";
	}

	cout << "\nstrong" << endl;

	ret.get();

	return 0;
}

09:17:14 **** Build of configuration Debug for project hello_world ****
make all 
Building file: ../src/hello_world.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -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   -lpthread
Finished building target: hello_world
 

09:17:15 Build Finished (took 1s.351ms)
forever
qiang yong yong yong qiang qiang qiang qiang qiang yong qiang yong yong qiang qiang qiang qiang qiang qiang qiang qiang qiang 
strong

4.4 std::async - launch::deferred

//============================================================================
// 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>       // std::cout
#include <future>         // std::async, std::future

using namespace std;

void print_task()
{
	for (int i = 0; i < 6; i++)
	{
		cout << "yong ";
	}
}

int main()
{
	future<void> ret = async(launch::deferred, print_task);

	cout << "forever" << endl;

	for (int i = 0; i < 16; i++)
	{
		cout << "qiang ";
	}

	cout << "\nstrong" << endl;

	ret.get();

	return 0;
}

09:20:30 **** Build of configuration Debug for project hello_world ****
make all 
Building file: ../src/hello_world.cpp
Invoking: GCC C++ Compiler
g++ -std=c++0x -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   -lpthread
Finished building target: hello_world
 

09:20:31 Build Finished (took 1s.347ms)
forever
qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang qiang 
strong
yong yong yong yong yong yong 

std::async 创建异步任务,并执行传递任务,任务只要是 callable object 即可,然后返回 std::futurestd::future 储存多线程共享的状态,当调用 future.get() 时会阻塞直到绑定的任务执行完毕。

  • std::launch::async - 在返回的 future 失效前会强制执行 print_task,不调用 future.get() 也会保证 print_task 的执行。
  • std::launch::deferred - 仅当调用 future.get() 时才会执行 print_task
  • 如果创建 async 时不指定 launch policy,默认 std::launch::async|std::launch::deferred,根据情况选择一种执行。

std::launch::deferred 创建 async 的时候并没有开启新线程执行任务,而是等到 future.get() 的时候才执行。

5. Complexity - 复杂度

destruction [dɪˈstrʌkʃn]:n. 破坏,毁灭,摧毁
trivially [ˈtrɪviəli]:adv. 琐细地,平凡地,无能地
destructible [dɪ'strʌktɪb(ə)l]:adj. 可破坏的,易损坏的

6. Data races - 数据竞争

The arguments are accessed to create decay copies.
访问参数以创建 decay copies

All visible side effects are synchronized between the call to async and the call to fn, and between its return point and the access to the returned future's share state.
所有可见的副作用在对 async 的调用与对 fn 的调用之间,其返回点与对返回的 future 共享状态的访问之间都是同步的。

7. Exception safety - 异常安全性

Basic guarantee: if an exception is thrown, all objects involved are left in a valid state.
基本保证:如果引发异常,则所有涉及的对象都将保持有效状态。

This member function throws an exception on the following conditions:
该成员函数在以下情况下引发异常:

exception type (异常类型) error condition (错误条件) description (描述)
system_error errc::resource_unavailable_try_again The system is unable to start a new thread (系统无法启动新线程)

Depending on the library implementation, this member function may also throw exceptions to report other situations.
根据库的实现,此成员函数还可能引发异常以报告其他情况。

If fn throws an exception, it is caught and stored in the shared state accessed by the returned future.
如果 fn 引发异常,则将其捕获并存储在返回的 future 访问的共享状态中。

assignment [ə'saɪnmənt]:n. 任务,布置,赋值

References

http://www.cplusplus.com/reference/future/async/

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

猜你喜欢

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