定义于头文件
- 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
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";
- }
