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

2023-11-01

C++11中的std::future是一个模板类。std::future提供了一种用于访问异步操作结果的机制std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared state that is not shared with any other asynchronous return objects (as opposed to std::shared_future))。一个future是一个对象,它可以从某个提供者的对象或函数中检索值,如果在不同的线程中,则它可以正确地同步此访问(A future is an object that can retrieve a value from some provider object or function, properly synchronizing this access if in different threads)。

有效的future是与共享状态(shared state)关联的future对象,可以通过调用以下函数(provider)来构造future对象:std::async、std::promise::get_future、std::packaged_task::get_future。future对象仅在它们是有效时才有用。

std::aysnc介绍参考:https://blog.csdn.net/fengbingchun/article/details/104133494

std::promise介绍参考:https://blog.csdn.net/fengbingchun/article/details/104124174

std::packaged_task介绍参考:https://blog.csdn.net/fengbingchun/article/details/104127352

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

1. 构造函数:(1).不带参数的默认构造函数,此对象没有共享状态,因此它是无效的,但是可以通过移动赋值的方式将一个有效的future值赋值给它;(2).禁用拷贝构造;(3).支持移动构造。

2. 析构函数:销毁future对象,它是异常安全的。

3. get函数:(1).当共享状态就绪时,返回存储在共享状态中的值(或抛出异常)。(2).如果共享状态尚未就绪(即提供者尚未设置其值或异常),则该函数将阻塞调用的线程直到就绪。(3).当共享状态就绪后,则该函数将取消阻塞并返回(或抛出)释放其共享状态,这使得future对象不再有效,因此对于每一个future共享状态,该函数最多应被调用一次。(4).std::future<void>::get()不返回任何值,但仍等待共享状态就绪并释放它。(5).共享状态是作为原子操作(atomic operation)被访问。

4. operator=:(1).禁用拷贝赋值。(2).支持移动赋值:如果在调用之前,此对象是有效的(即它已经访问共享状态),则将其与先前已关联的共享状态解除关联。如果它是与先前共享状态关联的唯一对象,则先前的共享状态也会被销毁。

5. share函数:获取共享的future,返回一个std::shared_future对象,该对象获取future对象的共享状态。future对象将不再有效。

6. valid函数:检查共享状态的有效性,返回当前的future对象是否与共享状态关联。一旦调用了std::future::get()函数,再调用此函数将返回false。

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

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

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

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

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

namespace future_ {

///
// reference: http://www.cplusplus.com/reference/future/future/
int test_future_1()
{
{ // constructor/get/operator=
	auto get_value = []() { return 10; };
	std::future<int> foo; // default-constructed
	std::future<int> bar = std::async(get_value); // move-constructed

	int x = bar.get();
	std::cout << "value: " << x << '\n'; // 10

	//int x2 = bar.get(); // crash, 对于每个future的共享状态,get函数最多仅被调用一次
	//std::cout << "value: " << x2 << '\n';

	std::future<int> foo2(std::async(get_value));
	std::cout << "value: " << foo2.get() << '\n'; // 10
}

{ // share
	std::future<int> fut = std::async([]() { return 10; });
	std::shared_future<int> shfut = fut.share();

	//std::cout << "value: " << fut.get() << '\n'; // crash, 执行完fut.share()后,fut对象将变得无效
	std::cout << "fut valid: " << fut.valid() << '\n';// 0

	// shared futures can be accessed multiple times:
	std::cout << "value: " << shfut.get() << '\n'; // 10
	std::cout << "its double: " << shfut.get() * 2 << '\n'; // 20, 对于std::shared_future对象,get函数可以被多次访问
}

{ // valid
	std::future<int> foo, bar;
	foo = std::async([]() { return 10; });
	bar = std::move(foo);

	if (foo.valid()) std::cout << "foo's value: " << foo.get() << '\n';
	else std::cout << "foo is not valid\n"; // foo is not valid

	if (bar.valid()) std::cout << "bar's value: " << bar.get() << '\n'; // 10
	else std::cout << "bar is not valid\n";
}

{ // wait
	auto is_prime = [](int x) {
		for (int i = 2; i < x; ++i) if (x%i == 0) return false;
		return true;
	};

	// call function asynchronously:
	std::future<bool> fut = std::async(is_prime, 194232491);

	std::cout << "checking...\n";
	fut.wait();

	std::cout << "\n194232491 ";
	if (fut.get()) // guaranteed to be ready (and not block) after wait returns
		std::cout << "is prime.\n";
	else
		std::cout << "is not prime.\n";
}

{ // wait_for
	auto is_prime = [](int x) {
		for (int i = 2; i < x; ++i) if (x%i == 0) return false;
		return true;
	};

	// call function asynchronously:
	std::future<bool> fut = std::async(is_prime, 700020007);

	// do something while waiting for function to set future:
	std::cout << "checking, please wait";
	std::chrono::milliseconds span(100);
	while (fut.wait_for(span) == std::future_status::timeout) // 可能多次调用std::future::wait_for函数
		std::cout << '.';

	bool x = fut.get(); // retrieve return value
	std::cout << "\n700020007 " << (x ? "is" : "is not") << " prime.\n";
}

	return 0;
}

///
// reference: https://en.cppreference.com/w/cpp/thread/future
int test_future_2()
{
	// future from a packaged_task
	std::packaged_task<int()> task([] { return 7; }); // wrap the function
	std::future<int> f1 = task.get_future();  // get a future
	std::thread t(std::move(task)); // launch on a thread

	// future from an async()
	std::future<int> f2 = std::async(std::launch::async, [] { return 8; });

#ifdef _MSC_VER
	// future from a promise
	std::promise<int> p;
	std::future<int> f3 = p.get_future();
	std::thread([&p] { p.set_value_at_thread_exit(9); }).detach(); // gcc 4.9 don't support this function
#endif

	std::cout << "Waiting..." << std::flush;
	f1.wait();
	f2.wait();
#ifdef _MSC_VER
	f3.wait();
#endif
	std::cout << "Done!\nResults are: " << f1.get() << ' ' << f2.get() << ' '
#ifdef _MSC_VER
		<< f3.get()
#endif
		<< '\n';
	t.join();

	return 0;
}

///
// reference: https://thispointer.com/c11-multithreading-part-8-stdfuture-stdpromise-and-returning-values-from-thread/
void initiazer(std::promise<int> * promObj)
{
	std::cout << "Inside Thread" << std::endl;
	promObj->set_value(35);
}

int test_future_3()
{
	std::promise<int> promiseObj;
	std::future<int> futureObj = promiseObj.get_future();
	std::thread th(initiazer, &promiseObj);
	std::cout << "value: " << futureObj.get() << std::endl;
	th.join();

	// If std::promise object is destroyed before setting the value the calling get() function on associated std::future object will throw exception.
	// A part from this, if you want your thread to return multiple values at different point of time then
	// just pass multiple std::promise objects in thread and fetch multiple return values from thier associated multiple std::future objects.

	return 0;
}

} // namespace future_

GitHubhttps://github.com/fengbingchun/Messy_Test

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

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

  • C++中的虚函数表介绍

    在C 语言中 当我们使用基类的引用或指针调用一个虚成员函数时会执行动态绑定 因为我们直到运行时才能知道到底调用了哪个版本的虚函数 所以所有虚函数都必须有定义 通常情况下 如果我们不使用某个函数 则无须为该函数提供定义 但是我们必须为每一个虚
  • C++/C++11中头文件algorithm的使用

  • 在Ubuntu 18.04上支持C++17的std::filesystem的方法

    在Ubuntu 18 04上通过命令sudo apt install gcc g 安装的gcc g 版本为7 5 此版本并不直接支持filesystem 如下图所示 Ubuntu 18 04上的g 7 5支持experimental的fil
  • C和C++安全编码笔记:指针诡计

    指针诡计 pointer subterfuge 是通过修改指针值来利用程序漏洞的方法的统称 可以通过覆盖函数指针将程序的控制权转移到攻击者提供的外壳代码 shellcode 当程序通过函数指针执行一个函数调用时 攻击者提供的代码将会取代原本
  • 程序员的自我修养--链接、装载与库笔记:可执行文件的装载与进程

    可执行文件只有装载到内存以后才能被CPU执行 1 进程虚拟地址空间 程序和进程有什么区别 程序 或者狭义上讲可执行文件 是一个静态的概念 它就是一些预先编译好的指令和数据集合的一个文件 进程则是一个动态的概念 它是程序运行时的一个过程 很多
  • C++11中头文件atomic的使用

    原子库为细粒度的原子操作提供组件 允许无锁并发编程 涉及同一对象的每个原子操作 相对于任何其他原子操作是不可分的 原子对象不具有数据竞争 data race 原子类型对象的主要特点就是从不同线程访问不会导致数据竞争 因此从不同线程访问某个原
  • OpenCV代码提取:遍历指定目录下指定文件的实现

    OpenCV 3 1之前的版本 在contrib目录下有提供遍历文件的函数 用起来比较方便 但是在最新的OpenCV 3 1版本给去除掉了 为了以后使用方便 这里将OpenCV 2 4 9中相关的函数给提取了出来 适合在Windows 64
  • Linux下遍历指定目录的C++实现

    之前在 https blog csdn net fengbingchun article details 51474728 给出了在Windows遍历指定文件夹的C 实现 这里给出在Linux下遍历目录的实现 Windows和Linux下的
  • 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++中typeid的使用

    RTTI Run TimeType Information 运行时类型信息 它提供了运行时确定对象类型的方法 在C 中 为了支持RTTI提供了两个操作符 dynamic cast和typeid The typeid operator pro
  • 概率论中伯努利分布(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
  • 进程间通信(IPC)的方法:命名管道

    使用管道时 一个进程的输出可成为另外一个进程的输入 命名管道 Named pipe或FIFO 是一种类似于管道的特殊文件 但在文件系统上有一个名称 它允许以先进先出 FIFO first in first out 的方式存储有限数量的数据
  • C++/C++11中头文件iterator的使用

  • C++17中utf-8 character literal的使用

    一个形如42的值被称作字面值常量 literal 这样的值一望而知 每个字面值常量都对应一种数据类型 字面值常量的形式和值决定了它的数据类型 由单引号括起来的一个字符称为char型字面值 双引号括起来的零个或多个字符则构成字符串型字面值 字
  • Linux下getopt函数的使用

    getopt为解析命令行参数函数 它是Linux C库函数 使用此函数需要包含系统头文件unistd h getopt函数声明如下 int getopt int argc char const argv const char optstri
  • C++/C++11中变长参数的使用

    C C 11中的变长参数可以应用在宏 函数 模板中 1 宏 在C99标准中 程序员可以使用变长参数的宏定义 变长参数的宏定义是指在宏定义中参数列表的最后一个参数为省略号 而预定义宏 VA ARGS 则可以在宏定义的实现部分替换省略号所代表的
  • 提高C++性能的编程技术笔记:单线程内存池+测试代码

    频繁地分配和回收内存会严重地降低程序的性能 性能降低的原因在于默认的内存管理是通用的 应用程序可能会以某种特定的方式使用内存 并且为不需要的功能付出性能上的代价 通过开发专用的内存管理器可以解决这个问题 对专用内存管理器的设计可以从多个角度
  • 有没有办法以保证无等待的方式检查 std::future 状态是否准备好?

    我知道我可以检查的状态std future通过以下方式 my future wait for std chrono seconds 0 std future status ready 但根据cppreference com std futu
  • 错误:命名空间“std”中没有名为“async”的成员

    我知道std async是 C 11 的事情 但我很确定我的编译器支持 C 11 include
  • 为什么 std::future 与 std::packaged_task 和 std::async 返回的不同?

    我知道了原因future从返回std async有一些特殊的共享状态wait on returned future发生在 future 的析构函数中 但是当我们使用std pakaged task 其未来不会表现出相同的行为 要完成打包任务

随机推荐

  • 离散时间信号处理_数字信号处理DSP(一)离散时间信号与系统

    基本介绍 1 所用课本 数字信号处理 第三版 作者 吴镇扬 高等教育出版社 2 本章简介 本章的内容比较基础 主要是复习一遍之前学过的知识 如 信号与系统 强化一下概念 为后续的课程作铺垫 相当于是 工具章 注意 我只会挑着我认为根据本校课
  • L2-1 盲盒包装流水线PTA

    众所周知 PAT 有 9 枚徽章 分别对应青铜 白银 黄金 白金 钻石 大师 王者 大圣 天神这 9 个段位 只有成绩非常优秀的考生才有资格获得刻有自己名字的徽章 现在 PAT 制作了徽章的小型纪念版 要制成盲盒给大家玩了 下图是一条盲盒包
  • 关于选择排序的了解

    1 选择排序与冒泡排序很像 它的实现是通过寻找最大值并放到合适的位置来实现 2 举个栗子 对于数组arr 5 3 8 1 9 2 来说 首先将第一个值设为初始值 与剩下的进行比较后交换 排在第一个 依次下去 直到排完 排完第一个后 从第二个
  • 综述:图像滤波去噪的常用算法实现及原理解析

    综述 图像滤波常用算法实现及原理解析 目录 综述 图像滤波常用算法实现及原理解析 前言 目录 自适应中值滤波 中值滤波器 自适应中值滤波器 自适应中值滤波算法描述 自适应中值滤波原理说明 算法实现 高斯滤波 高斯滤波实现方式一 高斯滤波实现
  • HTML5防止页面跳转的几种实现方式 2021-08-15

    防止页面跳转的几种实现方式 有没有什么方法可以防止点击连接时防止页面跳转呢 以下方法供参考 1 a href test a 点击链接 页面默认上滚到页的顶部 可以加上 nclick return false 防止上滚到页的顶部 2 a hr
  • 实验一-波士顿房价预测

    sklearn库安装 pip install scikit learn 波士顿数据 以Scikit learn的内置数据集波士顿 Boston 房屋价格为案例 采用单变量线性回归算法对数据进行拟合与预测 波士顿房屋的数据于1978年开始统计
  • HBase系列(五)Hive关联HBase

    Hive与HBase数据同步 方案一 Hive表关联HBase表 1 HBase表存在的情况 创建HBaseb表 HBase表插入数据 创建Hive表 查询映射好的Hive表 2 HBase表不存在的情况 创建Hive表 插入数据到Hive
  • ONNX动态输入和动态输出问题

    记录一下最近遇到的ONNX动态输入问题 1 一个tensor的动态输入数据 首先是使用到的onnx的torch onnx export 函数 贴一下官方的代码示意地址 ONNX动态输入 首先我们要有个tensor输入 比如网络的输入是bat
  • ctfshow-WEB-web12( 利用代码执行漏洞读取敏感文件)

    ctf show WEB模块第12关是一个代码执行漏洞 flag藏在根目录下的一个文件中 读取文件内容接口过关 进入页面后 只有一句话 where is the flag 按照以往的经验 线索肯定就藏在前端页面的源代码中 右键检查或者按F1
  • SQL建立日期维度表

    工作中一些项目 特别是系统或看板开发过程中 因为要保证日期在特定区间可能需要建立一张日期维度表 每天取过去某个日期到当天的日期 MySQL操作 MySQL可以编写并调用存储过程来实现 create table dim dim date DI
  • 线程和委托:在MFC里面实现线程的实例

    线程是一种从软件到硬件的技术 主要目的是为了提高运行速度 和多任务 需要储备的资料 他人的 http haobinnan blog 51cto com 775253 658446 多线程概述 进程和线程都是操作系统的概念 进程是在基于内存的
  • 修改virt-manager默认磁盘格式

    默认情况下 kvm环境 virt manager创建的虚机 磁盘格式为raw 如果要修改默认格式 见下图 此对应的配置文件为 more root gconf apps virt manager new vm gconf xml
  • stm32 SD(SDSC)卡的学习SDIO 模式连接SD卡

    本次的SD卡连接使用的是SDIO模式与之前的SPI模式相对应 都是对stm32 使用SD卡的介绍也为了和后面的FATFS文件系统使用铺垫 就直接上源码 也有看不明白的抢先看上一节的stm32 SD SDSC 卡的学习与SPI 模式应用 卡槽
  • vscode远程调试PHP代码

    一 准备工作 1 安装vscode里面的两个扩展 php Debug和Remote SSH 2 安装对应PHP版本的xdebug 去xdebug官方 复制自己的phpinfo源码到方框里 xdebug官方网址 https xdebug or
  • 映射实体类添加非数据库字段后@Transient不起作用

    映射如果用xml文件的话添加非数据库字段没有问题 注解的方式添加非数据库字段有问题 需要添加 Transient 注解 如果添加后不能成功 原因 jar包选错了 这里我选择了 java beans所以除了错 正确的包 import java
  • Effective java 总结9-异常

    Effective java 总结9 异常 第69条 只针对异常情况才使用异常 异常应该只被用于异常的情况下 永远不应该用于正常的控制流 设计良好的API也不应该强迫他的客户端使用异常控制流 可用 for Iterator
  • Hive动态分区

    Hive动态分区 一 hive中支持两种类型的分区 静态分区SP static partition 动态分区DP dynamic partition 静态分区与动态分区的主要区别在于静态分区是手动指定 而动态分区是通过数据来进行判断 详细来
  • Go语言必会面试题

    文章目录 1 下面代码有什么问题吗 2 下面代码输出什么 请说明 3 关于 slice 或 map 操作 下面正确的是 4 下面代码输出什么 5 关于字符串连接 下面语法正确的是 6 下面代码能编译通过吗 可以的话 输出什么 1 下面代码有
  • MySQL性能监控

    MySQL数据库监控一般主要关注连接数 缓存 事务和锁 慢查询等几项指标 1 MySQL连接数 MYSQL数据库默认最大连接数是100 然而对于流量稍微大一点的论坛或网站这个连接数是远远不够的 当并发数过大的时候会出现连接数不够用 使得很多
  • C++11中std::future的使用

    C 11中的std future是一个模板类 std future提供了一种用于访问异步操作结果的机制 std future所引用的共享状态不能与任何其它异步返回的对象共享 与std shared future相反 std future r