C++ 标准库中,有两种期望值,使用两种类型模板实现,声明在 <future> 头文件中 :
唯一期望值 (unique futures)( std::future<> )
共享期望值 (shared futures)( std::shared_future<> )。
对于简单的一次性事件,比如,在后台运行计算结果, 但是std::thread 并不提供直接接收返回值的机制。
使用std::async和std::future来实现:
#include <unistd.h> #include <future> #include <iostream> int calculator(int a, int b) { return a + b; } int main() { //使用 std::async 启动一个异步任务,返回一个 std::future 对象 std::future<int> the_answer = std::async(calculator, 1, 1); sleep(2); // do something //调用对象的get(),阻塞返回计算结果 std::cout << "the answer is " << the_answer.get() << std::endl; return 0; }
std::async允许添加额外的函数参数,具体实例如下:
struct X{ void foo(int, std::string const&); std::string bar(std::string const&); }; X x; auto f1 = std::async(&X::foo, &x,42, "Hello"); //调用p->foo(42,"hello"),p是指向x的指针 auto f2 = std::async(&X::bar, x, "goodbye"); //调用tmpx.bar("goodbye"),tmpx是x的拷贝副本 struct Y{ double operator()(double); }; Y y; auto f3 = std::async(Y(), 3.141); //调用tmpy(3.141),tmpy通过Y的移动构造函数得到 //使用std::ref可以在模板传参的时候传入引用,否则无法传递 auto f4 = std::async(std::ref(y), 2.718); //调用y(2.718) X baz(&x); std::async(baz, std::ref(x)); //调用baz(x)
在默认情况下,期望值是否等待取决于std::async 是否启动一个线程,或是否有任务正在进行同步。
还可以在函数调用之前向 std::async 传递 std::lanuch 或 std::launch::defered,表明函数调用被延迟到wait()或get()函数调用时才执行,std::launch::async 表明函数必须在其所在的独立线程上执行。如下:
auto f6 = std::async(std::launch::async, Y(), 1, 2); //在新线程上执行 auto f7 = std::async(std::launch::deferred, std::ref(x)); //在wait()或get()调用时执行 auto f8 = std::async(4. std ::launch ::deferred | std ::launch ::async, baz, std ::ref(x)); //实现选择执行方式 auto f9 = std::async(baz, std ::ref(x)); f7.wait(); //调用延迟函数
在上面的实例中,我们使用std::async让算法分割在各个任务中,从而实现并发。
当然,我们还可以通过其他方法关连 std::future 与任务实例,如,将任务包装入 std::package_task<>实例中
或使用std::promise<>l类型模板显示设置值。