【C++11并发】future库 笔记

简介

C++11之前,主线程要想获取子线程的返回值,一般都是通过全局变量,或者类似机制。C++11开始为我们提供了一组方法来获取子线程的返回值,并保证其原子性。

头文件

#include <future>

std::promise

在promise中保存了一个值或者异常,可以通过与其关联的 std::future 来获取这个值或者异常。常规用法

promise有两个特化的版本

template< class R > class promise;    // 普通类模板
template< class R > class promise<R&>;    // 引用特化
template<> class promise<void>;    // void特化

promise提供的方法
在这里插入图片描述
构造方法

promise();    // 默认构造方法
template< class Alloc >
promise( std::allocator_arg_t, const Alloc& alloc );    // cppreference上说是基于一个共享状态构造promise,还没有深入研究具体怎么用
promise( promise&& other ) noexcept;    // 移动构造方法
promise( const promise& other ) = delete;    // 删除了拷贝构造方法

析构方法
析构的时机有两个

  • promise内部共享状态为ready时
  • 如果promise的状态没有被设置为ready析构时,会将std::future_error异常保存到共享状态里

和构造方法类似,promise只支持移动赋值操作符

promise& operator=( promise&& other ) noexcept;
promise& operator=( const promise& rhs ) = delete;

获取future,如果get_future是被重复调用的,那么就会抛出std::future_error异常。如果想多个地方获取future,需要使用std::shared_future,他可以通过std::future构造。这是std::shared_future相应的构造方法的声明:shared_future( std::future&& other )

std::future<R> get_future();

设置共享数据,以及将共享状态设置为ready。由于promise有特化版本,下面声明的方法有些版本没有。另外,如果重复调用set_value会抛出std::future_error异常,即set_value只能调用一次。

void set_value( const R& value );    // member only of generic promise template
void set_value( R&& value );     //member only of generic promise template
void set_value( R& value );     // member only of promise<R&> template specialization
void set_value();    // 设置共享状态为ready

设置异常,以及将共享状态设置为ready,例子

void set_exception( std::exception_ptr p );

set_value_at_thread_exit 和 set_exception_at_thread_exit 类似set_value 和 set_exception,不同点是 xx_at_thread_exit 是在线程结束的时候将共享状态设置为ready,而set_xx 是立刻设置为ready。

std::future

future类是获取异步操作返回的封装。promise相当于是set,future相当于是get

类似promise,future也有两个特化版本

template< class T > class future;
template< class T > class future<T&>;
template<> class future<void>;

future提供的方法
在这里插入图片描述
构造方法

future() noexcept;    // 不关联任何共享状态
future( future&& other )     // 移动构造
future( const future& other ) = delete;    // 拷贝构造被删除

只有移动赋值操作符

future& operator=( future&& other ) noexcept;
future& operator=( const future& other ) = delete;

从构造方法和移动赋值操作符可以看出,future是唯一关联共享状态的,如果想多个future关联一个共享状态,future是不行的,需要将其转为std::shared_future。对应的方法是share:

std::shared_future<T> share() noexcept;

share方法内部是这么构造shared_future的:std::shared_future(std::move(*this)),所以调用share方法后,原理的future就不在关联共享状态了,也就不能再调用相关get方法,否则会抛出异常

std::shared_future

和std::future唯一的不同就是,std::shared_future可以多个对象同时关联同一个共享状态。他的特化版本、提供的方法和std::future也基本类似:
在这里插入图片描述

std::packaged_task

将可调用对象(函数,lambda表达式,仿函数等)包装后,可以异步调用,通过std::future获取返回值。参考代码

std::packaged_task 提供的方法
在这里插入图片描述

构造方法

packaged_task() noexcept;template< class F >
explicit packaged_task( F&& f );    // f为可调用对象,他是一个万能引用,即构造package_task的时候,可以传递给他可调用对象的左值,右值,左值引用,右值引用;参考:https://zhuanlan.zhihu.com/p/99524127template< class F, class Allocator >
explicit packaged_task( std::allocator_arg_t, const Allocator& a, F&& f );    // C++17删除了该方法packaged_task( const packaged_task& ) = delete;packaged_task( packaged_task&& rhs ) noexcept;    // 移动构造方法

析构方法
如果在共享状态设置为ready之前析构package_task,会抛出 std::future_errc::broken_promise 异常

只有移动赋值操作符

packaged_task& operator=( const packaged_task& ) = delete;
packaged_task& operator=( packaged_task&& rhs ) noexcept;

判断package_task对象是否有共享状态,比如用无参的构造方法构造的对象,就没有共享状态

bool valid() const noexcept;

获取future,如果重复调用get_future,会抛出std::future_error异常;另外,如果valid()方法返回为false,调用get_future,也会抛出std::future_error异常

std::future<R> get_future();

执行保存的可调用对象,和get_future一样重复调用,或者pakage_task对象没有共享状态,都会抛出std::future_error异常

void operator()( ArgTypes... args );

在线程结束,局部变量释放后,将共享状态设置为ready。抛出异常的情况和operator()一样

void make_ready_at_thread_exit( ArgTypes... args );

重置package_task的共享状态,等价于 *this = packaged_task(std::move(f)), f 是可调用对象。此时会构造新的共享状态,如果没有足够内存,会抛出std::bad_alloc异常。如果package_task对象没有共享状态,就会抛出std::future_error异常

void reset();

std::async

异步直行一个可调用对象
在这里插入图片描述

enum class launch : /* unspecified */ {async =    /* unspecified */,    // 立刻异步直行deferred = /* unspecified */,    // /* implementation-defined */
};

当使用launch::deferred时,只有future调用get或者wait方法时,才会异步直行可调用对象

cppreference

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/164865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 的字符串格式化指南

字符串格式化 Python 中控制字符串格式通常有三种形式&#xff1a; % 占位符&#xff08;格式化符&#xff09;str.format() 函数f-string 内嵌式 Python 最先开始格式化字符串是用 %&#xff0c;但它的致命缺点是支持的类型有限制&#xff0c;只支持 int&#xff0c;str&am…

【从零开始实现意图识别】中文对话意图识别详解

前言 意图识别&#xff08;Intent Recognition&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一个重要任务&#xff0c;它旨在确定用户输入的语句中所表达的意图或目的。简单来说&#xff0c;意图识别就是对用户的话语进行语义理解&#xff0c;以便更好地回答用户…

XUbuntu22.04之解决gpg keyserver receive failed no data(一百九十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

DevExpress WinForms TreeMap组件,用嵌套矩形可视化复杂分层数据

DevExpress WinForms TreeMap控件允许用户使用嵌套的矩形来可视化复杂的平面或分层数据结构。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风…

中文rlhf数据集50w条数据解析

中文rlhf数据集50w条数据解析 解析代码数据名代码解析 解析代码 import jieba from tqdm import tqdm import re import pandas as pd import numpy as npdef find_non_english_text(text):pattern re.compile(r[^a-zA-Z])return pattern.sub(, text)def find_chinese_text(t…

教育数字化转型:塑造未来学习新范式

在国家教育数字化战略行动指引下&#xff0c;我国正积极推动数字化赋能教育高质量发展&#xff0c;以塑造教育发展的新优势。如今&#xff0c;随着科技新基建的普及和数字化赋能教育的深入推进&#xff0c;未来的教育模型正在逐渐形成。 在新的教育模型中&#xff0c;数字化学…

算法基础(python版本)

第二章 算法设计思想 一、搜索排序 1.排序算法 https://visualgo.net/zh/sorting (1)冒泡排序 # 思路&#xff1a; # (1)比较相邻元素&#xff0c;如果第一个比第二个大&#xff0c;则交换他们 # (2)第一轮下来&#xff0c;可以保证最后一个数一定是最大的&#xff1b;第二…

2023最全的Web自动化测试介绍

做测试的同学们都了解&#xff0c;做Web自动化&#xff0c;我们主要用Selenium或者是QTP。 有的人可能就会说&#xff0c;我没这个Java基础&#xff0c;没有Selenium基础&#xff0c;能行吗&#xff1f;测试虽然属于计算机行业&#xff0c;但其实并不需要太深入的编程知识&…

介绍一个功能强大的shopify app——TINYIMG

各位观众老爷&#xff0c;南来的北往的&#xff0c;东去的西走的&#xff0c;今天给大家推荐一个功能很强大的shopify app 当当当 那就是 tinyimg 这个app有多牛逼呢&#xff0c;且听我慢慢道来 首先这个app可以用来优化图片大小&#xff0c;给你的网站提提速 然后这个app还可…

Android使用AIDL+MemoryFile传递大数据

Android进程间通信经常会使用AIDL&#xff0c;简单方便&#xff0c;但是数据量有限制&#xff0c;超过一定值会报错&#xff1a; E !!! FAILED BINDER TRANSACTION !!! (parcel size 2073744) 可以通过使用AIDLMemoryFile传递大数据 新建AIDL接口&#xff1a; interface On…

CCFCSP试题编号:201803-2试题名称:碰撞的小球

一、题目描述 二、思路 1.首先妾身分析这个题目&#xff0c;想要解题&#xff0c;得得解决2个问题。 1&#xff09;判断小球到达端点或碰撞然后改变方向&#xff1b; 2&#xff09;每时刻都要改变位置 两个问题都比较好解决&#xff0c;1&#xff09;只要简单判断坐标&…

形态学操作—膨胀

在 OpenCV 中&#xff0c;图像形态学操作是一组基于图像形状的处理技术&#xff0c;其中膨胀&#xff08;Dilation&#xff09;是其中之一。膨胀操作可用于图像处理中的特征增强、去噪、分割和边缘检测等。其基本原理是利用结构元素&#xff08;Kernel 或 Structuring Element&…

Tomcat实现WebSocket即时通讯 Java实现WebSocket的两种方式

HTTP协议是“请求-响应”模式&#xff0c;浏览器必须先发请求给服务器&#xff0c;服务器才会响应该请求。即服务器不会主动发送数据给浏览器。 实时性要求高的应用&#xff0c;如在线游戏、股票实时报价和在线协同编辑等&#xff0c;浏览器需实时显示服务器的最新数据&#x…

UML建模图文详解教程06——顺序图

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;《UML面向对象分析、建模与设计&#xff08;第2版&#xff09;》吕云翔&#xff0c;赵天宇 著 顺序图概述 顺序图(sequence diagram&#xff0c;也…

(三)C语言之for语句概述

&#xff08;三&#xff09;C语言之for语句概述 一、使用for语句实现打印华氏温度与摄氏温度转换二、for语句概述三、练习 一、使用for语句实现打印华氏温度与摄氏温度转换 #include <stdio.h> /*当华氏温度为 0,20,40,...300时&#xff0c;打印出华氏温度与摄氏温度对照…

一个简单的QT应用示例

一个简单的QT应用示例&#xff1a;创建一个窗口程序。 首先&#xff0c;确保已经安装了Qt开发环境。接下来&#xff0c;按照以下步骤创建一个简单的窗口程序&#xff1a; 1. 打开Qt Creator&#xff0c;点击“新建文件或项目”。 2. 选择“应用程序”&#xff0c;然后点击“下…

【MATLAB】根轨迹的绘制及rltool工具的使用

目录 一、MATLAB中传递函数的表示二、rlocus函数绘制根轨迹1.常规根轨迹仿真示例2.参数根轨迹仿真示例3.零度根轨迹仿真示例 三、图形化工具rltool介绍 一、MATLAB中传递函数的表示 在绘制系统的根轨迹之前&#xff0c;需要知道传递函数在matlab中如何表示。 在matlab中&#…

VOC数据集和COCO数据集直接的相互转换

VOC数据集格式 get_list.py import os import random import shutil# 设置随机种子 random.seed(1000)# 判断Annotations和JpegImages是否对应 train_precent=0.8 label_path= "../../Annotations" print(os.path.abspath(label_path)) save="../Main" pr…

repo init报error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

repo init报error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed 1 repo init出错的信息2 解决方法 在ubuntu执行repo init的时候报了repo init报error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed这种错误&#xff0c;解决方法是需要更新本地…

PS给图片增加一个白色边框。

问题描述&#xff1a;PS如何给图片增加一个白色边框&#xff1f; 解决办法&#xff1a; 第一步&#xff1a;使用shiftAltA快捷键&#xff0c;在图片四周拉出一个灰白色的边框。如下图所示&#xff1a; 第二步&#xff0c;使用快捷键Ctrlshiftn新建一个图层。 并把新建的图层…