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

c++20 std::jthread 源码简单赏析与应用

std::jthread

说明:

std::jthread 是 C++20 中引入的一个新特性,它是线程库中的一个类,专门用于处理 std::thread 与 std::stop_token 和 std::stop_source 之间的交互,以支持更优雅和安全的线程停止机制。

std::stop_source控制线程标记。相当于g_bQuitFlag = true;

std::stop_token线程函数内检测结束标记。相当于while(!g_bQuitFlag){...};

作用1.可控制的线程结束,防止人工封装的线程结束控制变量不是线程安全的。2.线程结束后不必手工调用join();

源码简单赏析:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.29.30133\include\thread

下面代码可以复制出来浏览。

class jthread {
public:using id = thread::id;using native_handle_type = thread::native_handle_type;jthread() noexcept : _Impl{}, _Ssource{ nostopstate } {}template <class _Fn, class... _Args, enable_if_t<!is_same_v<remove_cvref_t<_Fn>, jthread>, int> = 0>_NODISCARD_CTOR explicit jthread(_Fn&& _Fx, _Args&&... _Ax) {if constexpr (is_invocable_v<decay_t<_Fn>, stop_token, decay_t<_Args>...>) //线程函数第一个参数为stop_token,如果客户端std::jthread jt(work, stop_source.get_token());使用自己的stop_source展开相当于//is_invocable_v<decay_t<_Fn>, stop_token, stop_token>为false,执行下面else为不使用this->_Ssource,这里很微妙!//如果客户端std::jthread jt(work);不使用自己的stop_source展开相当于is_invocable_v<decay_t<_Fn>, stop_token>为true//也就是说这个if判断了三种情况,1.线程函数第一个不为stop_token 2.线程函数第一个参数为stop_token且客户端使用自己的stop_source //3.线程函数第一个参数为stop_token且客户端使用不自己的stop_source{_Impl._Start(_STD forward<_Fn>(_Fx), _Ssource.get_token(), _STD forward<_Args>(_Ax)...);//按照使用this内置的stop_source::stop_token传给线程函数}else {_Impl._Start(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);//按照std::thread处理,不使joinable功能,那么this->request_stop();也无效。处于兼容性考虑吧}}~jthread() {_Try_cancel_and_join();//析构时可自动调用_Impl.joinable();_Ssource.request_stop();_Impl.join();}jthread(const jthread&) = delete;//不支持拷贝构造jthread(jthread&&) noexcept = default;//jthread依然是unique thread类型的jthread& operator=(const jthread&) = delete;//不支持赋值jthread& operator=(jthread&& _Other) noexcept {// note: the standard specifically disallows making self-move-assignment a no-op here// N4861 [thread.jthread.cons]/13// Effects: If joinable() is true, calls request_stop() and then join(). Assigns the state// of x to *this and sets x to a default constructed state._Try_cancel_and_join();//移动赋值时,先结束掉本线程,再移动源线程到this_Impl = _STD move(_Other._Impl);_Ssource = _STD move(_Other._Ssource);return *this;}//剩下的简单函数封装void swap(jthread& _Other) noexcept {_Impl.swap(_Other._Impl);_Ssource.swap(_Other._Ssource);}_NODISCARD bool joinable() const noexcept {return _Impl.joinable();}void join() {_Impl.join();}void detach() {_Impl.detach();}_NODISCARD id get_id() const noexcept {return _Impl.get_id();}_NODISCARD stop_source get_stop_source() noexcept {return _Ssource;}_NODISCARD stop_token get_stop_token() const noexcept {return _Ssource.get_token();}bool request_stop() noexcept {return _Ssource.request_stop();}friend void swap(jthread& _Lhs, jthread& _Rhs) noexcept {_Lhs.swap(_Rhs);}_NODISCARD static unsigned int hardware_concurrency() noexcept {return thread::hardware_concurrency();}private:void _Try_cancel_and_join() noexcept {if (_Impl.joinable()) {_Ssource.request_stop();_Impl.join();}}thread _Impl;//采用c++组合方式对std::thread进行薄薄的封装,是不是和std::queue差不多的方法?stop_source _Ssource;//使用std自己实现的原子操作类std::stop_source控制线程停止
};

应用:

根据源代码阅读衍生的几个例子。源代码和例子说的是一致的。

1.不使用jthread内置的stop_source相当于thread类,std::jthread::request_stop();将不起作用,方便于一个外置std::stop_source控制多个线程函数

#include <iostream>
#include <thread>
#include <chrono>void work(std::stop_token stop_token) {while (!stop_token.stop_requested()) {std::cout << "Working...\n";std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Stopping...\n";
}int main() {std::stop_source stop_source;std::jthread jt(work, stop_source.get_token());std::this_thread::sleep_for(std::chrono::seconds(3));stop_source.request_stop();return 0;
}

2.使用jthread内置的stop_source :

#include <iostream>
#include <thread>
#include <chrono>void work(std::stop_token stop_token) {while (!stop_token.stop_requested()) {std::cout << "Working...\n";std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Stopping...\n";
}int main() {std::jthread jt(work);std::this_thread::sleep_for(std::chrono::seconds(3));//这两行都没必要人工调用的jt.request_stop();//jt.join();//return 0;
}

3.当线程函数参数没有参数stop_token时,使用起来std::jthread::request_stop();不起作用。相当于std::thread:

#include <iostream>
#include <thread>
#include <chrono>void work() {while (1) {std::cout << "Working...\n";std::this_thread::sleep_for(std::chrono::seconds(1));}std::cout << "Stopping...\n";
}int main() {std::jthread jt(work);std::this_thread::sleep_for(std::chrono::seconds(3));jt.request_stop();jt.join();return 0;
}
//输出:
//Working...
//Working...
//Working...
//Working...
//...

结论:

功能过于强大,灵活,坑也比较多。功能少,呆板,也没有什么坑。其实没有什么坑,只不过没看过开源库源码。官方文档不足以表达,就像黑盒测试永远无法相当于白盒测试。常常碰一碰运气运行一下看起来没问题,黑盒看起来也没问题?官方文档std::jthread - cppreference.com

相关文章:

c++20 std::jthread 源码简单赏析与应用

std::jthread 说明&#xff1a; std::jthread 是 C20 中引入的一个新特性&#xff0c;它是线程库中的一个类&#xff0c;专门用于处理 std::thread 与 std::stop_token 和 std::stop_source 之间的交互&#xff0c;以支持更优雅和安全的线程停止机制。 std::stop_source控制…...

自动化测试里的数据驱动和关键字驱动思路的理解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 初次接触自动化测试时&#xff0c;对数据驱动和关键字驱动不甚理解&#xff0c;觉得有点故弄玄须…...

【30天精通Prometheus:一站式监控实战指南】第6天:mysqld_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们&#x1f44b;   欢迎加入【30天精通Prometheus】专栏&#xff01;&#x1f4da; 在这里&#xff0c;我们将探索Prometheus的强大功能&#xff0c;并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。&#x1f680;   Prometheus是云原生和DevOps的…...

浅析智能体开发(第二部分):智能体设计模式和软件架构

大语言模型&#xff08;LLM&#xff09;驱动的智能体&#xff08;AI Agent&#xff09;展现出许多传统软件所不具备的特征。不仅与传统软件的设计理念、方法、工具和技术栈有显著的差异&#xff0c;AI原生&#xff08;AI Native&#xff09;的智能体还融入了多种新概念和技术。…...

Unity学习笔记---Transform组件

组件介绍 Transform组件在每个游戏对象中都存在&#xff0c;且只存在一个。该组件保存了游戏对象的位置、平移、旋转、缩放等信息。 组件相关方法 //获取当前游戏对象的Transform组件this.transform; getObject.transform; GetComponent<Transform>();//属性 gameObje…...

springboot+jsp校园理发店美容美发店信息管理系统0h29g

前台管理:会员管理、会员预定、开单点单、收银结帐、技师提成 后台管理:数据维护、物料管理、数据查询、报表分析、系统设置等 灵活的付款方式&#xff0c;支持现金、挂帐、会员卡&#xff0c;同时支持多种折扣方式并可按用户要求设置多种结帐类型善的充值卡管理模块:支持优惠卡…...

css - sass or scss ?

总的来说&#xff0c;Sass 和 SCSS 提供的功能是一样的&#xff0c;选择哪种语法主要取决于你的个人或团队的偏好。...

html5 笔记01

01 表单类型和属性 input的type属性 单行文本框: typetext 电子邮箱 : typeemail 地址路径 : type url 定义用于输入数字的字段: typenumber 手机号码: typetel 搜索框 : typesearch 定义颜色选择器 : typecolor 滑块控件 : typerange 定义日期 :typedate 定义输入时间的控件…...

E5063A是德科技e5063a网络分析仪

181-2461-8938产品概述&#xff1a; 简  述&#xff1a; E5063A 是低成本网络分析仪&#xff0c;可提供优化的性能和功能&#xff0c;适用于测试简单的无源器件&#xff0c;例如天线、电缆、滤波器和 PCB 等。它利用工业标准 ENA 系列始终如一的测量架构&#xff0c;能够极…...

【星海随笔】微信小程序(二)

WXML 模板语法 - 数据绑定 在data中定义页面的数据 在页面对应的 .js 文件中&#xff0c;把数据定义到 data 对象中即可&#xff1a; Page({data: {// 字符串类型的数据info: init data,// 数据类型的数据msgList: [{msg: hello},{msg: world}]} })Mustache 语法的格式 把 …...

Python采集安居客租房信息

Python采集安居客租房信息 一、需求介绍二、完整代码一、需求介绍 本次采集的需求就是获取到页面中的所有信息: 将数据采集好之后保存为如下csv文件: 爬取的流程不再展开分析,完整代码附后。 二、完整代码 import csvimport requests from lxml import etreeclass Anju…...

Rust构造JSON和解析JSON

目录 一、Rust构造JSON和解析JSON 二、知识点 serde_json JSON 一、Rust构造JSON和解析JSON 添加依赖项 cargo add serde-json 代码&#xff1a; use serde_json::{Result, Value};fn main() -> Result<()>{//构造json结构 cpu_loadlet data r#"{"…...

Linux 信号捕捉与处理

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux知识分享⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; ​ 目录 前言 1. 信号的处理时机 1.1用户…...

桂林电子科技大学计算机工程学院、广西北部湾大学计信学院莅临泰迪智能科技参观交流

5月18日&#xff0c;桂林电子科技大学计算机工程学院副院长刘利民、副书记杨美娜、毕业班辅导员黄秀娟、广西北部湾大学计信学院院长助理刘秀平莅临广东泰迪智能科技股份有限公司产教融合实训基地参观交流。泰迪智能科技副总经理施兴、广西分公司郑廷和、梁霜、培训业务部孙学镂…...

Qt笔记:动态处理多个按钮点击事件以更新UI

问题描述 在开发Qt应用程序时&#xff0c;经常需要处理多个按钮的点击事件&#xff0c;并根据点击的按钮来更新用户界面&#xff08;UI&#xff09;&#xff0c;如下图。例如&#xff0c;你可能有一个包含多个按钮的界面&#xff0c;每个按钮都与一个文本框和一个复选框相关联…...

Excel模板计算得出表格看板

背景 表格看板及导出&#xff0c;单元格时间年是根据筛选器时间变化的 较往年和往年是计算单元格 思路 1.通过excel模板来把数据填入excel再数据清洗得到数据返回前端 2.数据填充&#xff0c;通过行列作为key 列如&#xff1a;key整体20241月&#xff0c;根据key匹配数据填…...

es数据备份和迁移Elasticsearch

Elasticsearch数据备份与恢复 前提 # 注意&#xff1a; 1.在进行本地备份时使用--type需要备份索引和数据&#xff08;mapping,data&#xff09; 2.在将数据备份到另外一台ES节点时需要比本地备份多备份一种数据类型&#xff08;analyzer,mapping,data,template&#xff09; …...

Oracle数据块之数据行中的SCN

从Oracle 10g开始&#xff0c;如果在表级别打开ROW DEPENDENCIES&#xff0c;业务数据行发生更改时会在数据块中进行登记。 可以通过DUMP数据块来观察上述SCN&#xff1a; &#xff08;1&#xff09;创建测试表&#xff0c;插入3条测试数据&#xff0c;插入一条提交一次。并调用…...

手写tomcat(Ⅱ)——Socket通信+tomcat静态资源的获取

Socket通信简介 参考文章&#xff1a;socket通讯原理及例程&#xff08;一看就懂&#xff09; socket是介于应用层&#xff08;http协议&#xff09;和传输层&#xff08;TCP/UDP协议&#xff09;之间的一层虚拟层 Socket是一个程序&#xff0c;符合TCP/UDP协议的规范&…...

解决Error: error:0308010C:digital envelope routines::unsupported的四种解决方案

问题描述&#xff1a; 报错&#xff1a;Error: error:0308010C:digital envelope routines::unsupported 报错原因&#xff1a; 主要是因为 nodeJs V17 版本发布了 OpenSSL3.0 对算法和秘钥大小增加了更为严格的限制&#xff0c;nodeJs v17 之前版本没影响&am…...

shell 脚本笔记2

3.env与set区别 env用于查看系统环境变量 set用于查看系统环境变量自定义变量函数 4.常用环境变量 变量名称含义PATH命令搜索的目录路径, 与windows的环境变量PATH功能一样LANG查询系统的字符集HISTFILE查询当前用户执行命令的历史列表 Shell变量&#xff1a;自定义变量 目标…...

aws eks集成wasm运行时并启动pod

参考资料 WebAssembly 在云原生中的实践指南&#xff0c;https://cloud.tencent.com/developer/article/2324065 作为一种通用字节码技术&#xff0c;wasm的初衷是在浏览器中的程序实现原生应用性能。高级语言将wasm作为目标语言进行编译并运行在wasm解释器中。和nodejs类似的…...

linux:切分大文件

文章目录 1. 前言2. 用法3. 例子 1. 前言 如果传输、存储过程中出现大文件&#xff0c;希望切分成小文件。在 Linux 中&#xff0c;可以使用多种工具来切分大文件&#xff0c;最常用的是 split 命令。split 命令可以将一个大文件按照指定大小切分成多个小文件。 2. 用法 spl…...

docker 配置文件使用经验,后续持续增加

1. 容器中如何访问主机服务 在docker容器、docker compose 中如何访问主机服务呢&#xff1f; docker容器 20.10.0 版本在 linux 新增 host.docker.internal 支持&#xff1a; docker run -it --add-hosthost.docker.internal:host-gateway alpine cat /etc/hosts 127.0.0.…...

Qml:键盘事件

import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("Test KeyEvent")//传递给活动窗口的QQuickWindow//传递给当前活动的Item&#xff08;focus为true&#xff09;&#xff0c;如没则找子节点中的&#xff0c;都没有则忽略Item{id:item1//focus:…...

Java列表导出时将附件信息压缩成一个zip

一&#xff1a;使用场景 在最近的工作当中遇到了一个需求&#xff0c;在列表导出时&#xff0c;不仅需要将列表信息导出为excel文件&#xff0c;同时也需要将列表每一条数据所对应的附件信息放在同一个文件夹当中&#xff0c;并且压缩成一个zip响应给浏览器。首先后端需要写两…...

简单美观易上手的 Docker Compose 可视化管理器 Dockge

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 Dockge 是 Uptime Kuma 作者的新作品&#xff0c;因此 UI 风格与 Uptime Kuma 基本一致&#xff0c;如果你正在使用 Uptime Kuma 的话&#xff0c;那么 Dockge 的 UI 设计应该也不会让你失望。Dockge 主打…...

贴片 RS8752XK 封装SOP-8 250MHz,2通道高速运放

传感器信号放大&#xff1a;在传感器应用中&#xff0c;RS8752XK可以用于放大微弱的传感信号&#xff0c;如压力、温度、光强等传感器的信号。 数据采集系统&#xff1a;在数据采集设备中&#xff0c;RS8752XK可以用于放大和调理模拟信号&#xff0c;以供模数转换器&#xff0…...

图论-最短路算法

1. Floyd算法 作用&#xff1a;用于求解多源最短路&#xff0c;可以求解出任意两点的最短路 利用动态规划只需三重循环即可&#xff08;动态规划可以把问题求解分为多个阶段&#xff09;定义dp[k][i][j]表示点i到点j的路径&#xff08;除去起点终点&#xff09;中最大编号不超…...

家政预约小程序05服务管理

目录 1 设计数据源2 后台管理3 后端API4 调用API总结 家政预约小程序的核心是展示家政公司提供的各项服务的能力&#xff0c;比如房屋维护修缮&#xff0c;家电维修&#xff0c;育婴&#xff0c;日常保洁等。用户在选择家政服务的时候&#xff0c;价格&#xff0c;评价是影响用…...