std::promise介绍及使用

2023-11-18

一、std::promise介绍

std::promise是C++11并发编程中常用的一个类,常配合std::future使用。其作用是在一个线程t1中保存一个类型typename T的值,可供相绑定的std::future对象在另一线程t2中获取。

在主函数(主线程)中声明 promise 及其对应的 future,在某个线程中传入 promise 并进行运算;
在另一个线程中出入 future, 可利用get得到前一个线程中计算的结果;

二、代码示例:

#include <iostream>
#include <future>
#include <chrono>
 
void Thread_Fun1(std::promise<int> &p)
{
	//为了突出效果,可以使线程休眠5s
	std::this_thread::sleep_for(std::chrono::seconds(5));
 
	int iVal = 233;
	std::cout << "传入数据(int):" << iVal << std::endl;
 
	//传入数据iVal
	p.set_value(iVal);
}
 
void Thread_Fun2(std::future<int> &f)
{
	//阻塞函数,直到收到相关联的std::promise对象传入的数据
	auto iVal = f.get();		//iVal = 233
 
	std::cout << "收到数据(int):" << iVal << std::endl;
}
 
int main()
{
	//声明一个std::promise对象pr1,其保存的值类型为int
	std::promise<int> pr1;
	//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
	std::future<int> fu1 = pr1.get_future();
 
	//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行
	std::thread t1(Thread_Fun1, std::ref(pr1));
	//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
	std::thread t2(Thread_Fun2, std::ref(fu1));
 
	//阻塞至线程结束
	t1.join();
	t2.join();
 
	return 1;
}

可以看到std::future对象fu1先是通过std::promise的函数get_future()与std::promise对象pr1相绑定,pr1在线程t1中通过set_value()传入共享数据,fu1在线程t2中通过阻塞函数get()获取到传入的数据。
示例1中传入的数据类型是int,前面介绍中说std::promise可以保存typename T的数据,那么可以保存函数指针吗?答案是可行的,请看示例

#include <iostream>
#include <future>
#include <chrono>
#include <functional>
 
//声明一个可调对象T
using T = std::function<int(int)>;		//等同于typedef std::function<int(int)> T;
 
int Test_Fun(int iVal)
{
	std::cout << "Value is:" << iVal << std::endl;
	return iVal + 232;
}
 
void Thread_Fun1(std::promise<T> &p)
{
	//为了突出效果,可以使线程休眠5s
	std::this_thread::sleep_for(std::chrono::seconds(5));
 
	std::cout << "传入函数Test_Fun" << std::endl;
 
	//传入函数Test_Fun
	p.set_value(std::bind(&Test_Fun, std::placeholders::_1));
}
 
void Thread_Fun2(std::future<T> &f)
{
	//阻塞函数,直到收到相关联的std::promise对象传入的数据
	auto fun = f.get();		//iVal = 233
 
	int iVal = fun(1);
 
	std::cout << "收到函数并运行,结果:" << iVal << std::endl;
}
 
int main()
{
	//声明一个std::promise对象pr1,其保存的值类型为int
	std::promise<T> pr1;
	//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
	std::future<T> fu1 = pr1.get_future();
 
	//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行
	std::thread t1(Thread_Fun1, std::ref(pr1));
	//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
	std::thread t2(Thread_Fun2, std::ref(fu1));
 
	//阻塞至线程结束
	t1.join();
	t2.join();
 
	return 1;
}

既然可以传函数对象,那么是否可以通过模板魔改,传入可变元函数?请看示例

#include <iostream>
#include <future>
#include <chrono>
#include <functional>
 
//声明一个可调对象F
using F = std::function<int(int, int, int&)>;		//等同于typedef std::function<int(int, int, int&)> F;
 
//函数可以改成任意参数,任意返回类型
int Test_Fun(int a, int b, int &c)
{
	//a = 1, b = 2
	c = a + b + 230;
	return c;
}
 
void Thread_Fun1(std::promise<F> &p)
{
	//为了突出效果,可以使线程休眠5s
	std::this_thread::sleep_for(std::chrono::seconds(5));
 
	std::cout << "传入函数Test_Fun" << std::endl;
 
	//传入函数Test_Fun
	p.set_value(std::bind(&Test_Fun, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
 
template<typename T, typename ...Args>
void Thread_Fun2(std::future<T> &f, Args&& ...args)
{
	//阻塞函数,直到收到相关联的std::promise对象传入的数据
	auto fun = f.get();		//fun等同于Test_Fun
 
	auto fResult = fun(std::forward<Args>(args)...);
 
	std::cout << "收到函数并运行,结果:" << fResult << std::endl;
}
 
int main()
{
	//声明一个std::promise对象pr1,其保存的值类型为int
	std::promise<F> pr1;
	//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
	std::future<F> fu1 = pr1.get_future();
 
	//声明一个变量
	int iVal = 0;
 
	//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行
	std::thread t1(Thread_Fun1, std::ref(pr1));
	//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
	std::thread t2(Thread_Fun2<F, int, int, int&>, std::ref(fu1), 1, 2, std::ref(iVal));
 
	//阻塞至线程结束
	t1.join();
	t2.join();
 
	//此时iVal的值变成233
 
	return 1;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::promise介绍及使用 的相关文章

  • 金特 + XNA (C#)

    是否可以使用jint http jint codeplex com操作使用 XNA C 创建的 3D 环境 并向该环境添加功能 再次使用 jint 作为 Jint 的贡献者 我会推荐你Jint http jint codeplex com
  • 在 C# 中使用“using”关键字避免多次处置的最佳实践

    当变量是 IDisposable 时 我们有using关键字来管理处置 但是如果我们在方法中返回值怎么办 using twice StringContent stringToStringContent string str using St
  • WebClient.DownloadDataAsync 冻结了我的 UI

    我在 Form 构造函数中的 InitializeComponent 之后有以下代码 using WebClient client new WebClient client DownloadDataCompleted new Downloa
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • 无法将 std::min 传递给函数,std::min 的副本有效

    Passing std min函数无法编译 我复制了 libcpp 声明std min进入我的源文件并且它可以工作 std 版本有什么问题 clang 和 gcc 也会发生同样的情况 在 Godbolt 上测试 https godbolt
  • 何时不使用承诺[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在阅读了数十篇关于 es6 Promise 有多伟大以及为什么我们应该实现它们的文章之后 我有这样的感觉 ALL我的 不平凡的 JavaScri
  • 在 ASP.NET MVC 中将模型从视图传递到控制器

    我正在 ASP NET MVC 中开发我的第一个应用程序 但遇到了一个我无法解决的问题 即使在阅读了整个互联网之后也是如此 因此 我有几个使用视图模型创建的视图 它们是报告 这些视图模型是根据用户选择标准填充的 我正在尝试构建一种接受模型并
  • C 中“complex”的默认类型

    根据我读过的文档 C99 和更高版本的支持float complex double complex and long double complex作为复杂类型 但是 此代码在使用时编译时不会发出警告gcc Wall Wextra inclu
  • 有什么方法可以重载 C# 中的扩展方法吗?

    我有以下模型模式 public abstract class PARENTCLASS public class CHILD A CLASS PARENTCLASS public static class EXTENSION public s
  • 静态类与类的实例

    我有一个静态类 用于访问我的公共属性 整个应用程序的全局属性 和我在应用程序运行期间使用的方法 例如 我在静态类中设置了一些属性 并且在应用程序运行时我可以从属性中获取值 但我可以使用单例模式创建非静态类并以相同的方式使用它 问题 对于我的
  • 在 C++11 中移出 stdpriority_queue 的元素

    最小的工作示例 include
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 将错误代码映射到 C++ 中的字符串

    将错误代码从枚举映射到字符串的更有效方法是什么 在 C 中 例如 现在我正在做这样的事情 std string ErrorCodeToString enum errorCode switch errorCode case ERROR ONE
  • 使用多线程进行矩阵乘法?

    我应该使用线程将两个矩阵相乘 有两件事 当我运行程序时 我不断得到 0 我还收到消息错误 对于每个错误 它在粗体行上显示 警告 从不兼容的指针类型传递 printMatrix 的参数1 我尝试打印输出 还要注意 第一个粗体块 这是我解决问题
  • doxygen c++:记录由“using”声明公开的私有继承成员

    作为一个例子 我有以下课程 class A public void methodOne class B private A public Brief description using A methodOne 我还没有找到强制 doxyge
  • 无法在 C# 中为 EventArgs 分配使用派生类型的事件处理程序

    所以我有一个事件声明如下 public event EventHandler OnChangeDetected 然后我有以下处理程序被分配给该事件 myObject OnChangeDetected OnTableChanged 我的理解是
  • 无法识别解决方案文件夹中的 Visual Studio 2017 Nuget.config

    我在使用 Visual Studio 2017 时遇到问题 新的解决方案不断引用 C Users yopa AppData Roaming NuGet Nuget config 中意外位置的 Nuget config 文件 我已将 nuge
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可
  • SQL Server“未找到网络路径”在不同环境中随机且不频繁地发生

    类似 如果不是同一个问题 随机遇到网络路径未找到异常 https stackoverflow com questions 38696448 network path not found exception encountered rando

随机推荐

  • matlab 神经网络设计多层隐含层_【MATLAB深度学习】多层神经网络

    多层神经网络 对于多层神经网络的训练 delta规则是无效的 因为应用delta规则训练必须要误差 但在隐含层中没有定义 输出节点的误差是指标准输出和神经网络输出之间的差别 但训练数据不提供隐藏层的标准输出 真正的难题在于怎么定义隐藏节点的
  • 【Python】`*args` 和 `**kwargs`的用法【最全详解】

    args 和 kwargs的用法 猛滴打开博客 发现实在有段时间没更新了 又刚好用到了 kwargs 遂想起了许久之前总结的这篇博客 夸张点说也算是自己的一个呕心沥血之作吧 相信不少同学在看大神的程序时 总会看见 args kwargs 这
  • Deep Ensemble Bootstrapped Q-Learning (Deep-EBQL)【代码复现】

    Deep EBQL理论基础 原文链接 Ensemble Bootstrapping for Q Learning Deep EBQL是EBQL的深度学习版本 也即是在DQN的基础上 引入集成的思想 解决DQN过估计的问题 深度版本的EBQL
  • 02-----libevent下载或者移植环境时报错(/usr/bin/ld: warning:xxx,needed by xxx,not found)

    这个问题 bin sh xx 命令 not found是非常常见的 更具体可以是下图的情况 两者是一样的 1 我第一次遇到这种情况时 发现是库版本不对 所以将这些动态库换一篇后解决 ln s usr local lib libevent c
  • VSCode编码特效

    下载插件 Power Mode 然后来到settings json文件进行修改配置 如果找不到 可以只搜索settings 代码中继续追加这部分代码 explorer confirmDelete false powermode enable
  • Es修改索引别名

    在使用ES时有时候我们需要修改索引信息 本文总结了如何修改索引信息 ES修改索引结构 在 ElasticSearch 中索引就类似于关系型数据库中 Table 的概念 如果要修改索引的一些关键信息时 要重建索引 具体步骤如下 新建索引 复制
  • 【HTML】用户名、身份证号、邮箱、验证

    为了使页面不是那么突兀 特地导入了这俩个bootstrap框架相关的包
  • 归纳总结MATLAB中与矩阵运算有关的算术运算符(加、减、乘、除、点乘、点除、乘方、转置等)

    运算是算法的基础 所以我们有必要了解我们使用的工具怎样实现矩阵的基本运算 这篇博文总结MATLAB中矩阵的算术运算符 目录 01 加法运算符 02 减法 相反数 运算符 03 元素乘积 点乘 运算符 04 元素右除 点除 运算符 05 元素
  • C盘爆满如何解决

    上外网找到几个法子 第3个方法和你购买了驱动精灵的C盘瘦身专家的清理系统休眠文件功能是一样的 法1 一种方法是使用Windows系统自带的磁盘清理工具 它可以帮助你删除一些不需要的文件 如临时文件 回收站中的内容 系统还原点等 释放磁盘空间
  • Cesium开发个射击游戏

    经常刷视频看到这类设计游戏 思索cesium能不能开发个这样的游戏 场景就基于遥感影像或者倾斜模型 于是历时3天 水平有限 开发出简易的设计游戏demo 效果视频在b站 源码连接就丢在视频评论区了 用cesium从零开始开发个射击游戏 哔哩
  • qt 目录操作(QDir 类)展示系统文件案例

    1 目录操作 QDir 类 QDir类提供对目录结构及其内容的访问 QDir用于操作路径名 访问有关路径和文件的信息以及底层文件系统 它还可以用于访问Qt的资源系统 Qt使用 作为通用目录分隔符 与 在URL中作用路径分隔符的方式相同 如果
  • C++开发象棋一 绘制棋盘

    这是我要和大家分享的基于C 和MFC开发的一个象棋程序 目的是练习编程实践和大家分享同时希望大家能给出指教 进入主题 一 棋盘分析 这是我绘制的棋盘 棋盘的组成由9条竖线和10条横线构成 这儿我们设置每条线间的间隔是50 二 绘制过程 1
  • wdatepicker默认时间为当前时间

    document ready function alert today document getElementById serviceTime value today function today var today new Date va
  • mybatis中的if-else的嵌套使用

    mybatis的if else的嵌套使用方法 案例一 if else 在mybatis的使用过程中 难免会存在使用if else的逻辑 但是实际是没有这种语法的 提供了choose标签来替代这种语法
  • C++回顾——引用和拷贝构造函数

    一 C 中的指针 C和C 指针的最重要的区别在于C 是一种类型要求更强的语言 C不允许随便地把一个类型的指针赋值给另一个类型 但允许通过void 来实现 C 不允许这样做 如果真想把某种类型当做别的类型处理 则必须显示地使用类型转换 二 C
  • lunix断点调试与查看对象

    断点调试命令 如何查看对象内部的属性与方法
  • [高光谱] 开源项目Hyperspectral-Classification Pytorch解析之main

    开源项目Hyperspectral Classification Pytorch解析之main py 编码方式 coding utf 8 项目简介 DEEP LEARNING FOR HYPERSPECTRAL DATA This scri
  • 解决在cmd情况下无法连接MySQL情况(无脑操作教程)

    在输入外部命令 mysql u root p的时候 出现下面的情况 网图 侵删 问题分析 可能是MySQL路径问题没有解决 解决方法 1 打开电脑高级设置 2 点击环境变量 3 找到path路径变量后 点击编辑 4 新建路径 此路径是我保存
  • Java实现图片裁剪预览功能

    在项目中 我们需要做些类似头像上传 图片裁剪的功能 ok看下面文章 需要插件 jQuery Jcrop 后端代码 package org csg upload import java awt Rectangle import java aw
  • std::promise介绍及使用

    一 std promise介绍 std promise是C 11并发编程中常用的一个类 常配合std future使用 其作用是在一个线程t1中保存一个类型typename T的值 可供相绑定的std future对象在另一线程t2中获取