栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[modern c++] std::future 与 std::async / std::promise / std::packaged

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[modern c++] std::future 与 std::async / std::promise / std::packaged

描述:

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 
#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;
	}
	
}

与 std::promise一起使用

todo

与 std::packaged_task 一起使用

todo

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/997745.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号