当前位置: 首页 > news >正文

c++11 多线程支持 (std::shared_future)

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

输出

 

相关文章:

  • webpack定制化 基础配置[基础、配置、初运行]
  • mysql基本语句:DQL(数据查询语言)
  • Android | 通过URL获取网络图片Bitmap格式
  • SpringCloud-01 Rest学习环境搭建笔记
  • 基于APB与I2C的多主多从架构设计 - Function Description
  • R语言 ggdendro_谱系图
  • Kafka原理及概念解释
  • Springboot-自定义Spring Boot Starter并推送到远端公服
  • 《奔跑吧,程序员:从零开始打造产品、技术和团队》 读书笔记
  • PHP - 各版本对比 - 整理
  • JAVA 常见算法(选择排序,二分查找)
  • 【dotnet】Unity IL2CPP Mono
  • HC32L110(五) Ubuntu20.04 VSCode的Debug环境配置
  • 牛客 NC24307 [USACO 2012 Dec S]Milk Routing
  • . Flume面试题
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • 2017-08-04 前端日报
  • Go 语言编译器的 //go: 详解
  • Gradle 5.0 正式版发布
  • HTTP中的ETag在移动客户端的应用
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • miaov-React 最佳入门
  • Promise面试题2实现异步串行执行
  • Selenium实战教程系列(二)---元素定位
  • windows下如何用phpstorm同步测试服务器
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 关于springcloud Gateway中的限流
  • ------- 计算机网络基础
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 如何编写一个可升级的智能合约
  • 入门到放弃node系列之Hello Word篇
  • 系统认识JavaScript正则表达式
  • 写代码的正确姿势
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 阿里云重庆大学大数据训练营落地分享
  • #### go map 底层结构 ####
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • (1) caustics\
  • (C语言)字符分类函数
  • (新)网络工程师考点串讲与真题详解
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .net core Swagger 过滤部分Api
  • .net mvc 获取url中controller和action
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • @RequestMapping用法详解
  • [20150707]外部表与rowid.txt
  • [BUG]vscode插件live server无法自动打开浏览器
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法
  • [C++进阶篇]STL中vector的使用
  • [CSS]文字旁边的竖线以及布局知识
  • [hibernate]基本值类型映射之日期类型