C++11中的std::async是个模板函数。std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行,共享状态将包含Fn返回的值并ready。
std::async有两个版本:
1.无需显示指定启动策略,自动选择,因此启动策略是不确定的,可能是std::launch::async,也可能是std::launch::deferred,或者是两者的任意组合,取决于它们的系统和特定库实现。
2.允许调用者选择特定的启动策略。
std::async的启动策略类型是个枚举类enum class launch,包括:
1. std::launch::async:异步,启动一个新的线程调用Fn,该函数由新线程异步调用,并且将其返回值与共享状态的访问点同步。
2. std::launch::deferred:延迟,在访问共享状态时该函数才被调用。对Fn的调用将推迟到返回的std::future的共享状态被访问时(使用std::future的wait或get函数)。
参数Fn:可以为函数指针、成员指针、任何类型的可移动构造的函数对象(即类定义了operator()的对象)。Fn的返回值或异常存储在共享状态中以供异步的std::future对象检索。
参数Args:传递给Fn调用的参数,它们的类型应是可移动构造的。
返回值:当Fn执行结束时,共享状态的std::future对象准备就绪。std::future的成员函数get检索的值是Fn返回的值。当启动策略采用std::launch::async时,即使从不访问其共享状态,返回的std::future也会链接到被创建线程的末尾。在这种情况下,std::future的析构函数与Fn的返回同步。
std::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489
详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,部分作了调整,详细内容介绍可以参考对应的reference:
-
#include "future.hpp"
-
#include <iostream>
-
#include <future>
-
#include <chrono>
-
#include <utility>
-
#include <thread>
-
#include <functional>
-
#include <memory>
-
#include <exception>
-
#include <numeric>
-
#include <vector>
-
#include <cmath>
-
#include <string>
-
#include <mutex>
-
-
namespace future_ {
-
-
///////////////////////////////////////////////////////////
-
// reference: http://www.cplusplus.com/reference/future/async/
-
int test_async_1()
-
{
-
auto 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;
-
};
-
-
// 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;
-
}
-
-
///////////////////////////////////////////////////////////
-
// reference: http://www.cplusplus.com/reference/future/launch/
-
int test_async_2()
-
{
-
auto print_ten = [](
char c,
int ms) {
-
for (
int i =
0; i <
10; ++i) {
-
std::this_thread::sleep_for(
std::chrono::milliseconds(ms));
-
std::
cout << c;
-
}
-
};
-
-
std::
cout <<
"with launch::async:\n";
-
std::future<
void> foo =
std::async(
std::launch::async, print_ten,
'*',
100);
-
std::future<
void> bar =
std::async(
std::launch::async, print_ten,
'@',
200);
-
// async "get" (wait for foo and bar to be ready):
-
foo.get();
// 注:注释掉此句,也会输出'*'
-
bar.get();
-
std::
cout <<
"\n\n";
-
-
std::
cout <<
"with launch::deferred:\n";
-
foo =
std::async(
std::launch::deferred, print_ten,
'*',
100);
-
bar =
std::async(
std::launch::deferred, print_ten,
'@',
200);
-
// deferred "get" (perform the actual calls):
-
foo.get();
// 注:注释掉此句,则不会输出'**********'
-
bar.get();
-
std::
cout <<
'\n';
-
-
return
0;
-
}
-
-
///////////////////////////////////////////////////////////
-
// reference: https://en.cppreference.com/w/cpp/thread/async
-
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 test_async_3()
-
{
-
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
-
-
///////////////////////////////////////////////////////////
-
// reference: https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/
-
int test_async_4()
-
{
-
using
namespace
std::chrono;
-
-
auto fetchDataFromDB = [](
std::
string recvdData) {
-
// Make sure that function takes 5 seconds to complete
-
std::this_thread::sleep_for(seconds(
5));
-
//Do stuff like creating DB Connection and fetching Data
-
return
"DB_" + recvdData;
-
};
-
-
auto fetchDataFromFile = [](
std::
string recvdData) {
-
// Make sure that function takes 5 seconds to complete
-
std::this_thread::sleep_for(seconds(
5));
-
//Do stuff like fetching Data File
-
return
"File_" + recvdData;
-
};
-
-
// Get Start Time
-
system_clock::time_point start = system_clock::now();
-
-
std::future<
std::
string> resultFromDB =
std::async(
std::launch::async, fetchDataFromDB,
"Data");
-
-
//Fetch Data from File
-
std::
string fileData = fetchDataFromFile(
"Data");
-
-
//Fetch Data from DB
-
// Will block till data is available in future<std::string> object.
-
std::
string dbData = resultFromDB.get();
-
-
// Get End Time
-
auto end = system_clock::now();
-
auto diff = duration_cast <
std::chrono::seconds> (end - start).count();
-
std::
cout <<
"Total Time Taken = " << diff <<
" Seconds" <<
std::
endl;
-
-
//Combine The Data
-
std::
string data = dbData +
" :: " + fileData;
-
//Printing the combined Data
-
std::
cout <<
"Data = " << data <<
std::
endl;
-
-
return
0;
-
}
-
-
}
// namespace future_
GitHub:https://github.com/fengbingchun/Messy_Test
转载:https://blog.csdn.net/fengbingchun/article/details/104133494