定义于头文件 <future>
template< class T > class shared_future; (1) (C++11 起)
template< class T > class shared_future<T&>; (2) (C++11 起)
template<> class shared_future<void>; (3) (C++11 起)
类模板 std::shared_future
提供访问异步操作结果的机制,类似 std::future ,除了允许多个线程等候同一共享状态。不同于仅可移动的 std::future (故只有一个实例能指代任何特定的异步结果),std::shared_future
可复制而且多个 shared_future 对象能指代同一共享状态。
若每个线程通过其自身的 shared_future
对象副本访问,则从多个线程访问同一共享状态是安全的。
构造函数
shared_future() noexcept; (1) (C++11 起)
shared_future( const shared_future& other ); (2) (C++11 起) (C++17 前)
shared_future( const shared_future& other ) noexcept; (C++17 起)
shared_future( std::future<T>&& other ) noexcept; (3) (C++11 起)
shared_future( shared_future&& other ) noexcept; (4) (C++11 起)
构造新的 shared_future
。
1) 默认构造函数。构造空的 shared_future ,它不指代共享状态,即 valid() == false 。
2) 构造与 other
指代同一共享状态的 shared_future ,若有共享状态。
3-4) 转移 other
所保有的共享状态给 *this 。构造后, other.valid() == false 且 this->valid() 返回与 other.valid() 在构造前会返回者相同的值。
参数
other | - | 用以初始化的另一 future 对象 |
析构函数
std::shared_future<T>::~shared_future
~shared_future(); (C++11 起)
若 *this 是指代共享状态的最后一个对象,则销毁共享状态。否则不做任何事。
赋值内容
std::shared_future<T>::operator=
shared_future& operator=( const shared_future& other ); (C++11 起)(C++17 前)
shared_future& operator=( const shared_future& other ) noexcept; (C++17 起)
shared_future& operator=( shared_future&& other ) noexcept; (2) (C++11 起)
shared_future& operator=( shared_future&& other ) noexcept; | (2) | (C++11 起) |
赋值另一 shared_future
的内容。
1) 释放任何共享状态并赋值 other
的内容给 *this 。赋值后, this->valid() == other.valid() 。
2) 释放任何共享状态并移动赋值 other
的内容给 *this 。赋值后, other.valid() == false 且 this->valid() 将产生与 other.valid() 在赋值前相同的值。
参数
other | - | 将转移状态给 *this 的 std::shared_future |
返回值
*this
检查 future 是否拥有共享状态
std::shared_future<T>::valid
bool valid() const noexcept; (C++11 起)
检查期货是否指代共享状态。
这是非默认构造或被移动的期货的仅有情况。不同于 std::future ,调用 get()
时不非法化 std::shared_future
的共享状态。
若在不指代共享状态的 shared_future
上调用任何析构函数、复制赋值运算符、移动赋值运算符或 valid
以外的成员函数,则行为未定义(尽管鼓励实现在此情况下抛出指示 no_state
的 std::future_error )。从 valid()
为 false
的 shared_future 对象移动或复制是合法的。
参数
(无)
返回值
若 *this 指代共享状态则为 true ,否则为 false 。
等待结果变得可用
std::shared_future<T>::wait
void wait() const; (C++11 起)
阻塞直至结果变得可用。调用后 valid() == true 。
若调用此函数前 valid()== false 则行为未定义。
参数
(无)
返回值
(无)
异常
(无)
注意
鼓励实现检测调用前 valid == false 的情况并抛出以 std::future_errc::no_state 为 error_condition 的 std::future_error 。
在同一 std::shared_future
上从多个线程调调用 wait 不安全;有意图的使用是令每个等待于同一共享状态上的线程拥有一个 std::shared_future
的副本。
调用示例
#include <iostream>
#include <future>
#include <thread>
int fib(int n)
{
if (n < 3)
{
return 1;
}
else
{
return fib(n - 1) + fib(n - 2);
}
}
int main()
{
std::shared_future<int> f1 = std::async(std::launch::async, []()
{
return fib(20);
});
std::shared_future<int> f2 = std::async(std::launch::async, []()
{
return fib(25);
});
std::cout << "waiting...\n";
f1.wait();
f2.wait();
std::cout << "f1: " << f1.get() << '\n';
std::cout << "f2: " << f2.get() << '\n';
}
输出
等待结果,如果在指定的超时间隔后仍然无法得到结果,则返回。
std::shared_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 起)
等待结果变得可用。阻塞直至经过指定的 timeout_duration
,或结果变为可用,两者的先到来者。返回值鉴别结果的状态。
此函数可能由于调度或资源争议延迟而阻塞长于 timeout_duration
。
推荐标准库用稳定时钟度量时长。若实现用系统时钟代替,则等待时间可能也对时钟调整敏感。
若调用此函数前 valid()== false 则行为未定义。
参数
timeout_duration | - | 要阻塞的最大时长 |
返回值
常量 | 解释 |
future_status::deferred | 要计算结果的函数仍未启动 |
future_status::ready | 结果就绪 |
future_status::timeout | 已经过时限 |
异常
时钟、时间点或时长在执行中可能抛的任何异常(标准库提供的时钟、时间点和时长决不抛出)。
注意
鼓励实现在调用前检测 valid == false 的情况并抛出以 future_errc::no_state 为 error_condition 的 future_error 。
等待结果,如果在已经到达指定的时间点时仍然无法得到结果,则返回。
std::shared_future<T>::wait_until
template< class Clock, class Duration >
std::future_status wait_until(
const std::chrono::time_point<Clock,Duration>& timeout_time ) const; (C++11 起)
wait_until
等待结果变为可用。它阻塞直至抵达指定的 timeout_time
,或结果变为可用,两者的先到来者。返回值指示 wait_until
为何返回。
若调用此函数前 valid()== false 则行为未定义。
参数
timeout_time | - | 要阻塞到的最大时间点 |
返回值
常量 | 解释 |
future_status::deferred | 要计算结果的函数仍未启动 |
future_status::ready | 结果就绪 |
future_status::timeout | 已经过时限 |
异常
时钟、时间点或时长在执行中可能抛的任何异常(标准库提供的时钟、时间点和时长决不抛出)。
注意
鼓励实现在调用前检测 valid == false 的情况并抛出以 future_errc::no_state 为 error_condition 的 future_error 。
使用倾向 timeout_time
的时钟,不要求是单调时钟。若不连续地调节时钟,则不对此函数的行为保证,但既存实现将 timeout_time
从 Clock
转换到 std::chrono::system_clock ,并委托 POSIX pthread_cond_timedwait 以令等待忠实于系统时钟,但非用户提供 Clock
的调节。任何情况下,由于调度或资源争议延迟,函数可能等待长于抵达 timeout_time
。
返回结果
std::shared_future<T>::get
const T& get() const; (1) (仅为泛型 shared_future 模板的成员) (C++11 起)
T& get() const; (2) (仅为 shared_future<T&> 模板特化的成员)(C++11 起)
void get() const; (3) (仅为 shared_future<void> 模板特化的成员)(C++11 起)
get
方法等待直至 shared_future
拥有合法结果并(依赖于使用哪个模板)获取它。它等效地调用 wait() 等待结果。
泛型模板和二个模板特化各含单个 get
版本。 get
的三个版本仅在返回类型有别。
若调用此函数前 valid() 为 false 则行为未定义。
参数
(无)
返回值
1) 到存储于共享状态的值的 const 引用。销毁共享状态后,通过此引用访问值是未定义行为。
2) 存储于共享状态的值的引用。
3) 无。
异常
若 future 所引用的共享状态中存储异常(例如,通过调用 std::promise::set_exception() ),则抛出该异常。
注意
鼓励实现在调用前检测 valid() 为 false 的情况,并抛出以 std::future_errc::no_state 为 error_condition 的 std::future_error 。
调用示例
#include <iostream>
#include <future>
#include <chrono>
int main()
{
std::promise<void> ready_promise, t1_ready_promise, t2_ready_promise;
std::shared_future<void> ready_future(ready_promise.get_future());
std::chrono::time_point<std::chrono::high_resolution_clock> start;
auto fun1 = [&, ready_future]() -> std::chrono::duration<double, std::milli>
{
t1_ready_promise.set_value();
ready_future.wait(); // 等待来自 main() 的信号
return std::chrono::high_resolution_clock::now() - start;
};
auto fun2 = [&, ready_future]() -> std::chrono::duration<double, std::milli>
{
t2_ready_promise.set_value();
ready_future.wait(); // 等待来自 main() 的信号
return std::chrono::high_resolution_clock::now() - start;
};
auto result1 = std::async(std::launch::async, fun1);
auto result2 = std::async(std::launch::async, fun2);
// 等待线程变为就绪
t1_ready_promise.get_future().wait();
t2_ready_promise.get_future().wait();
// 线程已就绪,开始时钟
start = std::chrono::high_resolution_clock::now();
// 向线程发信使之运行
ready_promise.set_value();
std::cout << "Thread 1 received the signal "
<< result1.get().count() << " ms after start\n"
<< "Thread 2 received the signal "
<< result2.get().count() << " ms after start\n";
}
输出