C++ 11 多线程之future

什么是std::future?

在C++ 11中std::future是一个绕不开的新特性,因为他的引入极大提高了大家编码的效率。std::future是一个类模板,它将存放着一个未来的变量,而这个变量可以通过std::future提供的成员函数std::future::get()来得到。

std::future从何而来?

std::future通常可以通过调用函数(provider)来构造对象,provider一般指std::async、std::promise、std::packaged_task

  • std::async 函数
  • std::promise::get_future:get_future 为 promise 类的成员函数
  • std::packaged_task::get_future: get_future为 packaged_task 的成员函数

如果std::future这个变量尚未被赋值之前,就有其他线程试图通过std::future::get()获取这个变量,那么这个调用std::future::get()线程将会被阻塞到这个变量可以获取为止,才会继续执行。

std::future的构成

在这里插入图片描述

  • 基础函数(构造、析构、赋值):
    std::future 的拷贝构造函数是被禁用的,只提供了默认的构造函数和移动构造函数。另外,std::future的赋值构造函数禁用,只提供了 move 赋值操作

  • share函数:获取共享的future,返回一个std::shared_future对象,该对象获取future对象的共享状态。future对象将不再有效。

  • valid函数:检查共享状态的有效性,返回当前的future对象是否与共享状态关联。一旦调用了std::future::get()函数,再调用此函数将返回false。

  • wait函数:等待共享状态就绪,如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用者的线程直至共享状态就绪后,该函数将取消阻塞并void返回。

  • wait_for函数:等待共享状态在指定的时间内(时间片)准备就绪,如果同样尚未就绪,则该函数将阻塞调用者的线程直到就绪或已达到设置超时的时间。
    此函数的返回值类型为枚举类future_status。

    • ready:共享状态已就绪或者异常;
    • timeout:在规定的时间内未就绪;
    • deferred:异步函数操作还没开始;
  • wait_until函数:等待共享状态在指定的时间点(时间点)准备就绪,如果同样尚未就绪,则该函数将阻塞调用者的线程直到就绪或已达到设置超时的时间。
    此函数的返回值类型为枚举类future_status,具体释义同上

代码释义
#include <future>
#include <iostream>
#include <chrono>
using namespace std;
namespace {
	
	int TestFunc(int x)
	{
		cout << "thread id=" << std::this_thread::get_id() << endl;
		int result = 0;
		for (int i = 0; i < x; i++) {
			result += 3;
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
		}
		return result;
	}
} // namespace
void Test_share()
{
	std::future<int>        ret_data        = std::async([] { return 50; });
	std::shared_future<int> shared_ret_data = ret_data.share();
	try {
		// share()后,ret_data对象将变得无效,调用空指针
		std::cout << "ret_data valid: " << ret_data.valid() << endl;
		std::cout << "ret_data get: " << ret_data.get() << endl;

	} catch (const std::future_error& e) {
		// exception: std::future_error
		std::cout << "future_error : " << e.what() << std::endl;
	}
	//std::shared_future对象,get函数可以被多次访问
	std::cout << "value: " << shared_ret_data.get() << endl;
	std::cout << "its double: " << shared_ret_data.get() * 2 << endl;
}
void Test_valid_get()
{
	std::future<int> ret_data = std::async([] { return 50; });
	cout << ret_data.valid() << endl;//获取有效性
	cout << ret_data.get() << endl; //first get
	cout << ret_data.valid() << endl;//获取有效性
	try {
		std::cout << "ret_data get: " << ret_data.get() << endl; // second get
	} catch (const std::future_error& e) {
		// exception: std::future_error
		std::cout << "future_error : " << e.what() << std::endl;
	}
}
void Test_wait()
{
	cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
	std::future<int> ret_data = std::async(TestFunc, 5);
	std::cout << "wait..." << endl;
	ret_data.wait();
	std::cout << "ready..." << endl;
	std::cout << "ret_data get: " << ret_data.get() << endl; // second get
}
void Test_wait_()
{	
	/*
	enum class future_status { // names for timed wait function returns
    ready,
    timeout,
    deferred
	};
	*/
	int call_sum = 0;
	while (cin >> call_sum) {
		cout << "thread id=" << std::this_thread::get_id() << " " << __FUNCTION__ << endl;
		std::future<int> ret_data = std::async(TestFunc, call_sum);
		std::cout << "wait start" << endl;
		std::chrono::milliseconds span(200);
		std::future_status        ret_state = ret_data.wait_for(span);//获取状态
		//std::future_status        ret_state =
		//	ret_data.wait_until(std::chrono::system_clock::now() + std::chrono::milliseconds(200)); //获取状态,200ms后
		std::cout << "wait end state=" << static_cast<int>(ret_state) << endl;
		try {
			std::cout << "ret_data get: " << ret_data.get() << endl; // second get
		} catch (const std::future_error& e) {
			// exception: std::future_error
			std::cout << "future_error : " << e.what() << std::endl;
		}
	}	
}
int main()
{
	Test_share();
	cout << "======================================================" << endl;
	Test_valid_get();
	cout << "======================================================" << endl;
	Test_wait();
	cout << "======================================================" << endl;
	Test_wait_();
	cout << "======================================================" << endl;
}

结果
在这里插入图片描述
在这里插入图片描述

引申std::shared_future

std::shared_future 与std::future接口基本一致。

与std::shared_future关系
  • std::shared_future对象可以通过std::future对象进行隐式转换,也可以通过显示调用std::future::share显示转换,在这两种情况下,原来的std::future对象都会无效。
  • 当你需要具有std::future的多个有效拷贝时会用到std::shared_future;或者多个使用者使用std::future时也会用到std::shared_future
主要在用法上有区别
  • 支持copy(拷贝构造函数,拷贝赋值操作);
  • get()是一个const成员函数,返回一个const reference指向“存储于shared state”的值,通过shared_future::get检索的值不会释放共享对象的所有权
  • 共享状态(shared state)的生存期至少要持续到与之关联的最后一个对象被销毁为止。

参考连接:future实现

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值