在多线程环境中,不管是传递lambda还是传递函数指针,再或者是传递函数对象给std::thread,都很难获取执行函数返回值。在以前,只能将结果以引用的形式作为线程函数参数的一部分以此保存返回值,但是仍然存在很大局限性,甚至不太美观。C++11引入的std::future可以有效解决这一问题。
std::future定义在头文件<future>中,提供了一种获取异步操作返回值的机制,不过通常与下列三个配合使用
- std::promise
- std::packaged_task
- std::async
这三个操作各有不同,但是都有一个共同点就是都提供了get_future接口用于获得与之关联的future,使用者(主线程)可以通过返回的future获得异步操作结果。
std::promise
简单来说,promise是一种用于消息传递的机制,或者说是提供存储值和异常的设施。当创建线程时可以将promise引用传给线程函数,当在线程函数(异步操作)中计算得知了主线程想要的结果后通过promise::set_value*等接口设置值(如果出现异常也可以设置异常)。而主线程可以通过从promise获取的future获取结果
示例:利用std::future和std::promise实现并发std::find函数
和并发std::accumulate的实现类似,首先计算合适的线程数,将给定区间拆分成若干小区间,并行执行查找操作,当找到结果后,通过std::promise设置查找结果,而主线程则通过std::future获取结果
#include <future>
#include <thread>
#include <vector>
#include <algorithm>
#include <cassert>
namespace parallel
{
template <class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value)
{
/*
* 计算合适的线程数
* std::thread::hardware_concurrency()用于返回当前系统支持的并发数
*/
auto count = std::distance(first, last);
auto avaThreadNums = std::thread::hardware_concurrency();
auto perThreadMinNums = 20;
auto maxThreadNums = ((count + (perThreadMinNums - 1)) & (~(perThreadMinNums - 1))) / perThreadMinNums;
auto threadNums =
avaThreadNums == 0 ?
maxThreadNums :
std::min(<