C++ 11中提供了异步操作相关类和函数,不同的类具备不同的功能,总体来说类主要有:std::future,std::promise,std::package_task,函数主要是std::async。
1 异步操作类
上面三个类的主要功能是:
1.1 std::future
在thread库中提供了该future访问异步操作的结果,由于异步结果不能马上取得,只能在未来某个时候进行获取,这个结果是一个未来值,因此叫做future。通过查询future状态获取结果,future由三种状态组成,分别是:
在实际编码中,可以通过判断这三种内部状态异步获取执行结果。代码示例如下:
std::cout << "checking, please wait";
std::chrono::milliseconds span (1000);
do{
status = fut.wait_for(span);
if(status == std::future_status::deferred)
{
std::cout << "\ndeferred" << std::flush;
}
else if(status == std::future_status::timeout)
{
std::cout << "\ntimeout" << std::flush;
}
else if(status == std::future_status::ready)
{
std::cout << "\ready" << std::flush;
}
}while(status != std::future_status::ready);
1.2 std::promise
使用std::promise可以实现在两个不同线程之间的数值传递。使用方法如下:
void print_set(std::promise<int> &pro)
{
std::cout << "set value: " << "100" << '\n';
pro.set_value(100);
}
void print_int (std::future<int>& fut) {
int x = fut.get();
std::cout << "value: " << x << '\n';
}
int main ()
{
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread th2 (print_set, std::ref(prom));
std::thread th1 (print_int, std::ref(fut));
th1.join();
th2.join();
return 0;
}
上面的代码运行结果如下:
set value: 100
value: 100
1.3 std::package_task
和std::promise类似,需要结合future使用,但不同的是std::package_task包装的是一个函数,以此方便异步调用。使用方法如下:
int Add(int x,int y)
{
return (x+y);
}
int main ()
{
std::packaged_task<int(int,int)> pFun(Add);
std::future<int> fut = pFun.get_future();
std::thread th2 (std::move(pFun), 3,2);
int iRes = fut.get();
std::cout<<"iRes="<<iRes<<std::endl;
th2.join();
return 0;
}
程序运行结果为:iRes=5
2 异步操作函数:async
相对前面的异步操作类,std::async要高级的多,且可以直接创建异步的task类,异步返回结果保存在future中,在获取线程函数返回结果时,使用get()获取返回值,如果不需要值则使用wait()方法。
std::async原型如下:
future<typename result_of<Fn(Args...)>::type>
async (launch::async|launch::deferred, Fn&& fn, Args&&... args);
原型参数说明如下:
async基本用法如下:
bool is_prime (int x) {
std::this_thread::sleep_for(std::chrono::seconds(3));
for (int i=2; i<x; ++i) if (x%i==0) return false;
return true;
}
int main ()
{
// call function asynchronously:
std::future<bool> fut = std::async (is_prime,444444443);
std::future_status status;
// do something while waiting for function to set future:
std::cout << "checking, please wait";
std::chrono::milliseconds span (1000);
do{
status = fut.wait_for(span);
if(status == std::future_status::deferred)
{
std::cout << "\ndeferred" << std::flush;
}
else if(status == std::future_status::timeout)
{
std::cout << "\ntimeout" << std::flush;
}
else if(status == std::future_status::ready)
{
std::cout << "\ready" << std::flush;
}
}while(status != std::future_status::ready);
bool x = fut.get(); // retrieve return value
std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n";
return 0;
}
上面代码的运行如果为:
checking, please wait
"\n444444443 is prime."
async是更高层次的异步操作,在实际编码时无需关注线程创建细节,就可以方便的获取线程执行状态和结果;一般情况下,默认使用launch::async参数。