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/

發佈了452 篇原創文章 · 獲贊 1723 · 訪問量 103萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章