std::future 可以用来获取所有异步操作的结果,一般情况下 std::future 都会和 std::async , std::promise 或 std::packaged_task 一起使用。
std::future 有一个 valid 状态,当且仅当其valid状态时true时,才可以使用它,std::async , std::promise 或 std::packaged_task 创建的 std::future 都是 valid == true的 ,如果自行使用 std::future 的构造函数创建一个实例,那么它一定不是 valid 的,可以把 valid 状态当做一个 std::future 是否和某个异步任务相关联的标志,valid == false 代表当前 std::future 实际没有关联任何异步任务。
因为其内部已经有关联的异步任务了,可以把valid看作是std::future是否初始化完成的标志,一般初始化都比较快,所以正常情况下invalid状态很少出现,一般只在没指定异步任务时出现。另外如果使用std::move把异步任务从某个std::future转移给另一个,那么之前那个std::future会变成invalid状态。
std::future 有两套阻塞等待函数 waitX() 和 get(), waitX()会在任务没有执行完毕的情况下一直阻塞或者阻塞等待一段时间,但是不会改变std::future的valid状态。
get() 会阻塞等待任务执行完毕并且返回任务的返回值,同时会把 std::future 的状态变成 invalid 状态。这个时候只有重新做 move 或者重新通过 std::async , std::promise 或 std::packaged_task 才能再次激活 std::future。
换句话说,每个std::future 只能 get 一次,重复 get 会导致抛异常,进而崩溃。
鉴于不能重复 get 的问题,很多情况下我们只和 void 返回值的可调用对象一起使用,然后不去调用get函数,只用wait作同步只用。
与 std::async 一起使用gcc 2.cpp -pthread -o 2
#include与 std::promise一起使用#include #include #include #include #include #include std::atomic bbb{false}; int func() { while(!bbb){ sleep(1); } std::cout << "func stop" << std::endl; return 99; } int main() { std::future ret; //没有关联任何任务,因此是invalid if(ret.valid()){ std::cout << "valid" << std::endl; }else{ std::cout << "invalid" << std::endl; } std::cout << "----------" << std::endl; std::future ret1 = std::async (std::launch::async,func); if(ret1.valid()){ std::cout << "before move ret1 : valid" << std::endl; }else{ std::cout << "before move ret1 : invalid" << std::endl; } ret = std::move(ret1); if(ret1.valid()){ std::cout << "after move ret1 : valid" << std::endl; }else{ std::cout << "after : invalid" << std::endl; } std::cout << "----------" << std::endl; //关联任务,因此是valid if(ret.valid()){ std::cout << "valid" << std::endl; }else{ std::cout << "invalid" << std::endl; } std::cout << "----------" << std::endl; //把任务停掉,仍然是valid bbb = true; //等待可执行对象执行完毕,如果在wait之前已经执行完毕,那么这里直接返回 ret.wait(); //wait 只是等待异步任务结束,不会重置当前std::future,因此还是valid if(ret.valid()){ std::cout << "valid" << std::endl; }else{ std::cout << "invalid" << std::endl; } std::cout << "----------" << std::endl; //get 会等待异步任务结束并获取结果,get会重置 std::future,因此会变成 invalid int result = ret.get(); if(ret.valid()){ std::cout << "valid" << std::endl; }else{ std::cout << "invalid" << std::endl; } }
todo
与 std::packaged_task 一起使用todo


![[modern c++] std::future 与 std::async / std::promise / std::packaged [modern c++] std::future 与 std::async / std::promise / std::packaged](http://www.mshxw.com/aiimages/31/997745.png)
