59 C++ 多线程 —— future的其他重要函数 wait_for(),wait_util()

wait_for(const chrono::duration &time)

返回值:future_status

参数:const chrono::duration &time

函数含义:

等待结果变得可用。阻塞直至经过指定的 timeout_duration ,或结果变为可用,两者的先到来者。返回值鉴别结果的状态。

此函数可能由于调度或资源争议延迟而阻塞长于 timeout_duration 。

推荐标准库用稳定时钟度量时长。若实现用系统时钟代替,则等待时间可能也对时钟调整敏感。

若调用此函数前 valid()== false 则行为未定义。

std::future<T>::wait_for



template< class Rep, class Period >
std::future_status wait_for( const std::chrono::duration<Rep,Period>& timeout_duration ) const;
  (C++11 起) 
   


例子:

//该方法,返回值是double,参数是string,在函数内部可以给一个 int赋值。赋值后的数据可以通过 resultint的实参.getfuture()获得
double promisefunc181(promise<int> &resultint, string strsource) {
	cout << "promisefunc181 start " << endl;
	// 计算完毕后,我们假设计算结果是1000,给resultint赋值
	resultint.set_value(1000);
	chrono::milliseconds dura(1000);
	this_thread::sleep_for(dura);
	cout << "promisefunc180 end " << endl;
	return 3.14;
}

//
void main() {
	//wait_for()函数使用演示
	string str3 = "chinabank";
	promise<int> promi3;
	shared_future<double> fu6 = async(launch::deferred, promisefunc181, ref(promi3), ref(str3));
	shared_future<int> fu7 = promi3.get_future();
	//fu6.get(); async在参数是deferred的时候,只有通过get()方法才能调用,且是在当前线程启动

	chrono::milliseconds dura(2000);
	future_status fustatus= fu6.wait_for(dura);

	if (future_status::deferred == fustatus) {
		cout << "status is deferred" << endl;
	}
	cout << "00000000000000000000" << endl;


	promise<int> promi4;
	shared_future<double> fu8 = async(launch::async, promisefunc181, ref(promi4), ref(str3));
	future_status fustatusfu8 = fu8.wait_for(2000ms);
	if (future_status::timeout == fustatusfu8) {
		cout << "status is timeout" << endl;
	}
	if (future_status::ready == fustatusfu8) {
		cout << "status is ready" << endl;
	}

	cout << "duandian " << endl;

}

wait_for()应用

通过wait_for();函数去check async方法在没有指定使用那种膜式下时,系统到底使用那种模式。

	//再没有参数(launch::async或者 launch::deferred)的情况下,我们怎么马上知道这行代码会使用那种模式运行呢?需要使用 wait_for参数,传递0
	promise<int> promi5;
	shared_future<double> fu9 = async(promisefunc181, ref(promi5), ref(str3));
	future_status fustatusfu9 = fu9.wait_for(chrono::seconds(0));
	if (future_status::deferred == fustatusfu9) {
		cout << "此行代码使用deferred模式运行" << endl;
		//如果这行代码一定要运行,在当前线程运行也可以那么这时候,你要使用get()方法让其运行
		fu9.get();
		//如果这行代码还必须要在子线程完成。那么就要写在子线程,这时候因为promi5已经用过了,就要重新弄一个promi6
		promise<int> promi6;
		async(launch::async,promisefunc181, ref(promi6), ref(str3));
	}
	else if(future_status::ready == fustatusfu9){
		cout << "此行代码使用async模式运行,且已经运行完毕,可以从future中get值了" << endl;
		double dou = fu9.get();
		cout << "douready = " << dou << endl;
	}
	else if (future_status::timeout == fustatusfu9) {
		cout << "此行代码使用async模式运行,但是超时了,可以调用 future中get中重新获得" << endl;
		double dou = fu9.get(); //调用 fu9.get(),去重新调用方法
		cout << "doutimeout = " << dou << endl;
	}

wait_util()

    wait_until 等待结果变为可用。它阻塞直至抵达指定的 timeout_time ,或结果变为可用,两者的先到来者。返回值指示 wait_until 为何返回。
    若调用此函数前 valid() 为 false ,或 Clock 不符合时钟(Clock) 要求则行为未定义。若 std::chrono::is_clock_v<Clock> 为 false 则程序为非良构。(C++20 起)
 

	//cout wait_util()方法,
	//wait_until 等待结果变为可用。它阻塞直至抵达指定的 timeout_time ,或结果变为可用,两者的先到来者。返回值指示 wait_until 为何返回。
	//若调用此函数前 valid() 为 false ,或 Clock 不符合时钟(Clock) 要求则行为未定义。若 std::chrono::is_clock_v<Clock> 为 false 则程序为非良构。(C++20 起)

	auto now = std::chrono::system_clock::now();//得到当前时间
	std::chrono::system_clock::time_point two_seconds_passed
		= std::chrono::system_clock::now() + std::chrono::seconds(2);
	promise<int> promi11;
	shared_future<double> fu11 = async(launch::async, promisefunc181, ref(promi11), ref(str3));
	future_status fustatusfu11 = fu11.wait_until(std::chrono::system_clock::now() + std::chrono::seconds(2));

	if (future_status::deferred == fustatusfu11) {
		cout << "fustatusfu11 == future_status::deferred"<<endl;
		cout << fu11.get() << endl;
	}
	else if (future_status::ready == fustatusfu11) {
		cout << "fustatusfu11 == future_status::ready" << endl;
		cout << fu11.get() << endl;
	}
	else if (future_status::timeout == fustatusfu11) {
		cout << "fustatusfu11 == future_status::timeout" << endl;
		cout << fu11.get() << endl;
	}

wait()

阻塞直至结果变得可用。如果没有future没有执行完毕,则一直在这里阻塞等候。

std::experimental::future



在标头 <experimental/future> 定义
   

template< class T > class future;
 (1) (并发 TS) 

template< class T > class future<T&>;
 (2) (并发 TS) 

template<>          class future<void>;
 (3) (并发 TS) 
   

类模板 std::experimental::future 以下列操作扩展 std::future :
?使用 future<future<T>> 的解包装构造函数;
?查询关联共享状态是否就绪的 is_ready ;以及
?附着持续到期货的成员函数 then 。

然而, std::experimental::future 与 std::future 间无相互操作。

成员函数



(构造函数)
  构造 future 对象
(公开成员函数) 


is_ready
  检查共享状态是否就绪
(公开成员函数) 


then
  附着持续到 future
(公开成员函数) 


operator=
  移动 future 对象
(公开成员函数) 





等同于 std::future 的成员

成员函数

注意 share() 返回 std::experimental::shared_future<T> 。其他行为等同。



(析构函数)
  析构 future 对象
(std::future<T> 的公开成员函数) 


share
  从 *this 转移共享状态给 shared_future 并返回它
(std::future<T> 的公开成员函数) 

设置结果
 


get
  返回结果
(std::future<T> 的公开成员函数) 

状态
 


valid
  检查 future 是否拥有共享状态
(std::future<T> 的公开成员函数) 


wait
  等待结果变得可用
(std::future<T> 的公开成员函数) 


wait_for
  等待结果,如果在指定的超时间隔后仍然无法得到结果,则返回。
(std::future<T> 的公开成员函数) 


wait_until
  等待结果,如果在已经到达指定的时间点时仍然无法得到结果,则返回。
(std::future<T> 的公开成员函数) 

bool valid() const noexcept;
   

检查期货是否指代共享状态。

返回值

若 *this 指代共享状态则为 true ,否则为 false 。

std::future<T>::valid

bool valid() const noexcept;
  (C++11 起) 
   

检查期货是否指代共享状态。

这是非默认构造或被移动的期货(例如为 std::promise::get_future() 、 std::packaged_task::get_future() 或 std::async() 所返回)在首次调用 get() 或 share() 前的唯一情况。

若在不指代共享状态的 future 上调用任何析构函数、移动赋值运算符或 valid 以外的成员函数,则行为未定义(尽管鼓励实现在此情况下抛出指示 no_state 的 std::future_error )。从 valid() 为 false 的 future 对象移动是合法的。

参数

(无)

返回值

若 *this 指代共享状态则为 true ,否则为 false 。