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
.
该函数在共享状态下临时存储使用的线程处理程序或 fn
和 args
的 decay 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
(就像一个线程对象是用 fn
和 args
作为参数构造的,并访问返回的 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
的共享状态 (使用 wait
或 get
)。此时,将调用 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).
Fn
和 Args ...
是模板参数:如果隐式推导,则它们是参数的正确左值或右值引用类型。不过请注意,该函数使用 fn
和 args...
的衰变副本 (有关使引用可复制的包装器类,请参见 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::type
是 Fn
返回的类型,当使用 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::future
。std::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. 任务,布置,赋值