C++11中std::shared_future的使用

2023-11-18

C++11中的std::shared_future是个模板类。std::future类似,std::shared_future提供了一种访问异步操作结果的机制;不同于std::future,std::shared_future允许多个线程等待同一个共享状态;不同于std::future仅支持移动操作,std::shared_future既支持移动操作也支持拷贝操作,而且多个shared_future对象可以引用相同的共享状态。std::shared_future还允许一旦共享状态就绪就可以多次检索共享状态下的值(A shared_future object behaves like a future object, except that it can be copied, and that more than one shared_future can share ownership over their end of a shared state. They also allow the value in the shared state to be retrieved multiple times once ready)。

std::shared_future对象可以通过std::future对象隐式转换,也可以通过显示调用std::future::share显示转换,在这两种情况下,原std::future对象都将变得无效。

共享状态(shared state)的生存期至少要持续到与之关联的最后一个对象被销毁为止。与std::future不同,通过shared_future::get检索的值不会释放共享对象的所有权。

std::future介绍参考:https://blog.csdn.net/fengbingchun/article/details/104115489

当你需要具有std::future的多个有效拷贝时会用到std::shared_future;或者多个使用者使用std::future时也会用到std::shared_future。

Consider std::future, std::shared_future to be like std::unique_ptr, std::shared_ptr.

模板类std::shared_future成员函数包括:

1. 构造函数:(1).不带参数的默认构造函数,此对象没有共享状态,因此它是无效的,但是它可以被赋予一个有效值;(2).拷贝构造:与const shared_future& x具有相同的共享状态,并与之共享所有权;(3).支持移动构造。

2. 析构函数:销毁shared_future对象,它是异常安全的。如果对象有效(即它可以访问共享状态),则将其与对象接触关联;如果它是与共享状态关联的唯一对象,则共享对象本身也将被销毁。

3. get函数:(1).当共享状态就绪时,返回存储在共享状态中的值的引用(或抛出异常)。(2).如果共享状态尚未就绪(即provider提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并返回(或抛出),但与future::get不同,不会释放其共享状态,允许其它shared_future对象也访问存储的值。(4).std::shared_future<void>::get()不返回任何值,但仍等待共享状态就绪才返回或抛出。

4. operator=:(1).拷贝赋值:该对象与const shared_future& rhs关联到相同的共享状态,并与之共享所有权;(2).移动赋值:该对象获取shared_future&& rhs的共享状态,rhs不再有效。

5. valid函数:检查共享状态的有效性,返回当前的shared_future对象是否与共享状态关联。

6. wait函数:(1).等待共享状态就绪。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将解除阻塞并void返回。

7. wait_for函数:(1).等待共享状态在指定的时间内(time span)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到设置的时间。(3).此函数的返回值类型为枚举类future_status。此枚举类有三种label:ready:共享状态已就绪;timeout:在指定的时间内未就绪;deferred:共享状态包含了一个延迟函数(deferred function)。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。

8. wait_until函数:(1). 等待共享状态在指定的时间点(time point)准备就绪。(2). 如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪或已达到指定的时间点。(3).此函数的返回值类型为枚举类future_status。(4).如果共享状态包含了一个延迟函数,则该函数不会阻塞,立即返回一个future_status::deferred值。

详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "future.hpp"
#include <iostream>
#include <future>
#include <chrono>
#include <utility>
#include <thread>

namespace future_ {

///
// reference: https://en.cppreference.com/w/cpp/thread/shared_future
int test_shared_future_1()
{
	std::promise<void> ready_promise, t1_ready_promise, t2_ready_promise;
	// 通过std::future移动构造std::shared_future对象,t1_ready_promise和t2_ready_promise均会用到ready_future
	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(); // waits for the signal from 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(); // waits for the signal from main()
		return std::chrono::high_resolution_clock::now() - start;
	};

	auto fut1 = t1_ready_promise.get_future();
	auto fut2 = t2_ready_promise.get_future();

	auto result1 = std::async(std::launch::async, fun1);
	auto result2 = std::async(std::launch::async, fun2);

	// wait for the threads to become ready
	fut1.wait();
	fut2.wait();

	// the threads are ready, start the clock
	start = std::chrono::high_resolution_clock::now();

	// signal the threads to go
	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";

	return 0;
}

///
// reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait
int fib(int n)
{
	if (n < 3) return 1;
	else return fib(n - 1) + fib(n - 2);
}

int test_shared_future_2()
{
	// 将std::shared_future<int>调整为std::future<int>也是正确的
	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';

	return 0;
}

///
// reference: https://en.cppreference.com/w/cpp/thread/shared_future/wait_for
int test_shared_future_3()
{
	// 将std::shared_future<int>调整为std::future<int>也是正确的
	std::shared_future<int> future = std::async(std::launch::async, [](){ 
        std::this_thread::sleep_for(std::chrono::seconds(3));
        return 8;  
    }); 
 
    std::cout << "waiting...\n";
    std::future_status status;
    do {
        status = future.wait_for(std::chrono::seconds(1));
        if (status == std::future_status::deferred) {
            std::cout << "deferred\n";
        } else if (status == std::future_status::timeout) {
            std::cout << "timeout\n";
        } else if (status == std::future_status::ready) {
            std::cout << "ready!\n";
        }
    } while (status != std::future_status::ready); 
 
    std::cout << "result is " << future.get() << '\n';

	return 0;
}

} // namespace future_

GitHubhttps://github.com/fengbingchun/Messy_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11中std::shared_future的使用 的相关文章

  • C++11中std::condition_variable的使用

  • C++11中std::lock_guard的使用

    互斥类的最重要成员函数是lock 和unlock 在进入临界区时 执行lock 加锁操作 如果这时已经被其它线程锁住 则当前线程在此排队等待 退出临界区时 执行unlock 解锁操作 更好的办法是采用 资源分配时初始化 RAII 方法来加锁
  • C和C++安全编码笔记:整数安全

    5 1 整数安全导论 整数由包括0的自然数 0 1 2 3 和非零自然数的负数 1 2 3 构成 5 2 整数数据类型 整数类型提供了整数数学集合的一个有限子集的模型 一个具有整数类型的对象的值是附着在这个对象上的数学值 一个具有整数类型的
  • C语言中的弱符号与强符号介绍

    弱符号 Weak symbol 是链接器 ld 在生成ELF Executable and Linkable Format 缩写为ELF 可执行和可链接格式 是一种用于可执行文件 目标文件 共享库和核心转储的标准文件格式 ELF文件有两种索
  • C和C++安全编码笔记:动态内存管理

    4 1 C内存管理 C标准内存管理函数 1 malloc size t size 分配size个字节 并返回一个指向分配的内存的指针 分配的内存未被初始化为一个已知值 2 aligned alloc size t alignment siz
  • C++中namespace detail或namespace internal的使用

    在很多开源代码中偶尔会使用名字为 detail 或 internal 的命名空间 如OpenCV的modules目录中 有些文件中使用了namespace detail 有些文件中使用了namespace internal 名为detail
  • C++11中std::function的使用

    类模版std function是一种通用 多态的函数封装 std function的实例可以对任何可以调用的目标实体进行存储 复制 和调用操作 这些目标实体包括普通函数 Lambda表达式 函数指针 以及其它函数对象等 通过std func
  • Windows下创建进程简介

    正在执行的应用程序称为进程 进程不仅仅是指令和数据 它还有状态 状态是保存在处理器寄存器中的一组值 如当前执行指令的地址 保存在内存中的值 以及唯一定义进程在任一时刻任务的所有其他值 进程与应用程序的一个重要的区别在于 进程运行时 进程的状
  • C和C++安全编码笔记:并发

    并发是一种系统属性 它是指系统中几个计算同时执行 并可能彼此交互 一个并发程序通常使用顺序线程和 或 进程的一些组合来执行计算 其中每个线程和进程执行可以在逻辑上并行执行的计算 这些进程和 或 线程可以在单处理器系统上使用分时抢占式的方式
  • C语言中signal函数简介及使用

    signal h是C标准函数库中的信号处理部分 定义了程序执行时如何处理不同的信号 信号用作进程间通信 报告异常行为 如除零 用户的一些按键组合 如同时按下Ctrl与C键 产生信号SIGINT C 中的对应头文件是csignal C语言标准
  • Linux下多线程编程互斥锁和条件变量的简单使用

    Linux下的多线程遵循POSIX线程接口 称为pthread 编写Linux下的多线程程序 需要使用头文件pthread h 链接时需要使用库libpthread a 线程是进程的一个实体 是CPU调度和分派的基本单位 它是比进程更小的能
  • 内存检测工具Dr. Memory的使用

    Dr Memory是一个内存调试工具 它是一个开源免费的内存检测工具 它能够及时发现内存相关的编程错误 比如未初始化访问 内存非法访问 数组越界读 写 以及内存泄露等 它可以在Linux Windows Mac OS和Android操作系统
  • C++11中std::bind的使用

    std bind函数是用来绑定函数调用的某些参数的 std bind它可以预先把指定可调用实体的某些参数绑定到已有的变量 产生一个新的可调用实体 它绑定的参数的个数不受限制 绑定的具体哪些参数也不受限制 由用户指定 std bind 1 将
  • C++14中返回类型推导的使用

    使用C 14中的auto返回类型 编译器将尝试自动推导 deduce 返回类型 namespace int xx 1 auto f return xx return type is int const auto f3 return xx r
  • C++中的封装、继承、多态

    封装 encapsulation 就是将抽象得到的数据和行为 或功能 相结合 形成一个有机的整体 也就是将数据与操作数据的源代码进行有机的结合 形成 类 其中数据和函数都是类的成员 封装的目的是增强安全性和简化编程 使用者不必了解具体的实现
  • C++中typeid的使用

    RTTI Run TimeType Information 运行时类型信息 它提供了运行时确定对象类型的方法 在C 中 为了支持RTTI提供了两个操作符 dynamic cast和typeid The typeid operator pro
  • CSV文件简介及C++实现

    逗号分隔值 Comma Separated Values CSV 有时也称为字符分隔值 因为分隔字符也可以不是逗号 其文件以纯文本形式存储表格数据 数字和文本 纯文本意味着该文件是一个字符序列 不含必须象二进制数字那样被解读的数据 CSV文
  • 概率论中伯努利分布(bernoulli distribution)介绍及C++11中std::bernoulli_distribution的使用

    Bernoulli分布 Bernoulli distribution 是单个二值随机变量的分布 它由单个参数 0 1 给出了随机变量等于1的概率 它具有如下的一些性质 P x 1 P x 0 1 P x x x 1 1 x Ex x Var
  • C++14中binary literals的使用

    一个形如42的值被称作字面值常量 literal 这样的值一望而知 每个字面值常量都对应一种数据类型 字面值常量的形式和值决定了它的数据类型 我们可以将整型字面值写作十进制 基数为10 八进制 基数为8 或十六进制 基数为16 数的形式 以
  • 提高C++性能的编程技术笔记:单线程内存池+测试代码

    频繁地分配和回收内存会严重地降低程序的性能 性能降低的原因在于默认的内存管理是通用的 应用程序可能会以某种特定的方式使用内存 并且为不需要的功能付出性能上的代价 通过开发专用的内存管理器可以解决这个问题 对专用内存管理器的设计可以从多个角度

随机推荐

  • 百度网盘无法登陆,二维码不显示,密码、验证码登陆显示‘网络异常’解决方法

    如图所示 二维码加载不出来 账号也不能登陆 但是其他软件一切正常 IE重置 防火墙 注册表 卸载重装 各种方法都无法解决 解决办法 连接手机WiFi后二维码加载出来 问题解决 所以换一个网登陆就可以了
  • linux 和 windows usb插拔侦测

    1 windowsU口探测事件 设备事件 WM DEVICECHANGE 首先要创建一个窗口 把设备事件和窗口关联 HWND h CreateWindow TEXT USB EVENT TEXT 0 0 0 0 0 0 0 GetModul
  • c语言经典程序合集

    1 c语言计算自然数之和 计算自然数和 include
  • SpringBoot+ Mybatis plus 配置多个数据源 (MySql)

    首先配置 yml 然后创建对应的 配置文件 然后复制下方的代码 进行粘贴 Configuration MapperScan basePackages com example chassis mapper chassis mapper sql
  • 关于一个栈的输入顺序是a,b,c,d,e则下列序列中不可能是出栈顺序

    经常在笔试的时候会看见这样类似的笔试题 就是关于一个栈的输入顺序是a b c d e则下列序列中不可能是出栈顺序 很多人都知道栈是先进后出 但是还是做好这道题 以一道题目为例给大家讲讲这道题目应该怎么做 题目 一个栈的输入顺序是a b c
  • 【Linux】深入理解文件操作

    文章目录 初次谈论文件 重温C语言文件操作 系统文件操作接口 open write read 再次谈论文件 文件描述符 文件描述符的分配规则 重定向 什么是重定向 重定向的本质 系统调用接口实现重定向 lt gt gt gt 初次谈论文件
  • Spring Boot中获取当前Request和Response实例的方法

    获取Request HttpServletRequest request ServletRequestAttributes RequestContextHolder getRequestAttributes getRequest 获取Res
  • uni-app在App平台如何实现升级更新?

    使用 uni app 开发 可将代码编译到iOS Android 微信小程序等多个平台 升级时也需考虑多平台同步升级 uni app发布为小程序的升级模式较简单 只需将开发完的代码提交小程序后台 待审核通过后用户将自动升级 App端的升级
  • STM32CubeIDE(串口)

    目录 一 轮询模式 1 1 配置USART2为异步模式 1 2 500ms发送一次消息 1 3 通信结果 1 4 串口控制LED 二 中断收发 2 1 开启中断 2 2 中断发送接收 2 2 1 中断发送只需要调用接口 2 2 2 中断接收
  • 二、文件管理命令

    2 文件管理命令 2 1文件管理 2 1 1touch新建文件指令 touch 当文件不存在时命令为新建文件 当文件存在时命令为修改文件时间戳 touch file1 file2 新建多个文件 touch t 11111111 11 修改文
  • 【算法】邻居好说话——冒泡排序

    简化版的桶排序不仅仅有上一节所遗留的问题 更要命的是 它非常浪费空间 例如需要排序数的范围是0 2100000000之间 那你则需要申请2100000001个变量 也就是说要写成int a 2100000001 因为我们需要用2100000
  • 关于EasyUI Datagrid JSON对象内嵌对象的取值问题

    如有这样一个JSON对象 1 goods 2 id 1 category id 1 name category1 name NameA shelfLife 12 3 id 1 category id 1 name category1 nam
  • 【hello Linux】进程间通信——共享内存

    目录 前言 1 System V共享内存 1 共享内存的理解 2 共享内存的使用步骤 3 共享内存的使用 1 共享内存的创建 查看共享内存 2 共享内存的释放 3 共享内存的挂接 4 共享内存的去挂接 4 共享内存的使用示例 1 两进程挂接
  • JavaWeb购物商城

    系统前台 前台用户操作 账号 test密码 test 登录页面 商品浏览 商品详情 购物车 订单页面 系统后台 后台用户操作 账号 admin密码 admin 用户登录页面 后台主页 添加商品 编辑商品 删除商品 数据库 部分代码 logi
  • matlab求傅里叶级数展开式_连续时间的傅里叶级数

    如果信号x t 是周期信号 那么对于所有t 存在一个最小正数T 使得x t x t T 其中 T 为这个周期信号的最小正周期 根据周期函数的周期性 x t x t N T N为整数 称为这个信号的基波频率 周期信号x t 也可以用周期复指数
  • 2020年全国高校计算机能力挑战赛初赛java语言解答

    题目1 统计从1到N的整数中 所有立方值的平方根为整数的数的格式 输入说明 整数N N lt 10000 输出说明 符合条件的数的个数 如4 3 64 8 2 输入样例 10 输出样例 3 说明 样例中符合条件的3个数是1 4 9 publ
  • Redis系列之安装配置

    前言 缓存Redis的讲解 作为第一个开篇文章 我们不谈高深的东西 从以下几个方面介绍下Redis 简介 安装 配置 启动 OK 下面我们就开始今天的缓存之旅吧 什么是Redis Redis是以Key value形式存储 和传统的关系型数据
  • Itext7填充PDF表单中文无法显示,‘凉’不显示问题

    Itext7填充PDF表单中文无法显示 凉 不显示问题 添加依赖
  • C#使用Sqlite总结

    1 下载Sqlite的dll 页面地址 http system data sqlite org index html doc trunk www downloads wiki 基于本项目的版本 下载Setups for 32 bit Win
  • C++11中std::shared_future的使用

    C 11中的std shared future是个模板类 与std future类似 std shared future提供了一种访问异步操作结果的机制 不同于std future std shared future允许多个线程等待同一个共