(C++20) jthread中stop_token的基础使用

news2024/11/24 18:41:11

(C++20) jthread中stop_token的基础使用

文章目录

  • (C++20) jthread中stop_token的基础使用
  • C++20 jthread
  • 使用方式
    • 循环判断
    • 条件变量condition_variable_any
  • stop回调 std::stop_callback
  • END

C++20 jthread

std::jthread - cppreference.com

std::stop_token - cppreference.com

std::stop_source - cppreference.com

在C++20中推出了jthread。其两个核心功能是:

  • 自动合并joining thread
  • 线程取消stop token

下面有两个重点:

std::jthread中有request_stop()操作能够原子的将关联的std::stop_source停止标志进行切换。

std::stop_token是对于关联的std::stop_source视图。


这里辅助打印使用一个基于RAII的技巧:

视频讲解:【细莲】(C++) 基于RAII的多线程类原子输出_哔哩哔哩_bilibili

class Writer {
    std::ostringstream buffer;

public:
    Writer() {
        buffer << std::this_thread::get_id();
    }
    ~Writer() {
        std::cout << buffer.str();
    }
    Writer& operator<<(auto input) {
        buffer << input;
        return *this;
    }
};

使用方式

循环判断

最普通的方式就是循环判断。这对于常见的线程封装来说很常见。

std::jthread能够接受一个第一个参数为std::stop_token stoken的函数。该sstoken与线程对象绑定。

#include <chrono>
#include <iostream>
#include <sstream>
#include <thread>

class Writer {
    std::ostringstream buffer;

public:
    Writer() {
        buffer << std::this_thread::get_id();
    }
    ~Writer() {
        std::cout << buffer.str();
    }
    Writer& operator<<(auto input) {
        buffer << input;
        return *this;
    }
};

void fun_jth_pass(std::stop_token stoken, long secCnt) {
    Writer() << "Test While Start" << '\n';
    // 直到请求停止
    do {
        std::this_thread::sleep_for(std::chrono::milliseconds(secCnt));
        Writer() << "Test While Running" << '\n';
    } while (!stoken.stop_requested());

    Writer() << "Test While End" << '\n';
}

int main() {
    std::cout << std::boolalpha;
    Writer() << ">>>Main Start\n";

    /**
     * 可以手动显示操作
     * 显示的请求结束和join
     */
    {
        std::jthread jth_pass(fun_jth_pass, 300);
        std::this_thread::sleep_for(std::chrono::seconds(1));
        if (jth_pass.joinable()) {
            Writer() << "request_stop() = " << jth_pass.request_stop() << '\n';
            jth_pass.join();
        }
    }

    Writer() << ">>>Main End\n";
}
11124>>>Main Start
20148Test While Start
20148Test While Running
20148Test While Running
20148Test While Running
11124request_stop() = 1
20148Test While Running
20148Test While End
11124>>>Main End

条件变量condition_variable_any

在多线程中单单使用循环判断一个标志是效率比较低的。如果能将一个线程进行挂起那CPU的效果会提升很多。

这里就需要介绍std::condition_variable_any

这里的wait()第二个参数就是std::stop_token,当外部停止请求stoken停止时,会自动唤醒cv_any

template< class Lock, class Predicate >
bool wait( Lock& lock, std::stop_token stoken, Predicate pred );
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <sstream>
#include <thread>

class Writer {
    std::ostringstream buffer;

public:
    Writer() {
        buffer << std::this_thread::get_id();
    }
    ~Writer() {
        std::cout << buffer.str();
    }
    Writer& operator<<(auto input) {
        buffer << input;
        return *this;
    }
};
void fun_jth_cv_any(std::stop_token stoken) {
    std::mutex       mutex;
    std::unique_lock lock(mutex);

    // `cv_any::wait`有`std::stop_token`的重载
    // `stoken`停止时,会自动唤醒`cv_any`
    std::condition_variable_any().wait(lock, stoken, [] {
        Writer() << "Test condition_variable_any::wait() Running" << '\n';
        return false;
    });
    Writer() << "Test condition_variable_any::wait() End" << '\n';
}

int main() {
    std::cout << std::boolalpha;
    Writer() << ">>>Main Start\n";

    /**
     * 基于RAII会自动停止stoken和进行join
     */
    {
        std::jthread jth_cv_any(fun_jth_cv_any);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    Writer() << ">>>Main End\n";
}
20416>>>Main Start
19876Test condition_variable_any::wait() Running
19876Test condition_variable_any::wait() Running
19876Test condition_variable_any::wait() Running
19876Test condition_variable_any::wait() End
20416>>>Main End

stop回调 std::stop_callback

可以对stop_token对象注册一个监控停止的回调。

当外部请求停止request_stop()时。会自动调用注册的callback。

其中回调函数的声明周期,跟随回调对象

template< class Callback >
class stop_callback;

template<class C>
explicit stop_callback( std::stop_token&& st, C&& cb ) noexcept(/*see below*/);

template<class C>
explicit stop_callback( const std::stop_token& st, C&& cb ) noexcept(/*see below*/);
#include <chrono>
#include <iostream>
#include <sstream>
#include <thread>

class Writer {
    std::ostringstream buffer;

public:
    Writer() {
        buffer << std::this_thread::get_id();
    }
    ~Writer() {
        std::cout << buffer.str();
    }
    Writer& operator<<(auto input) {
        buffer << input;
        return *this;
    }
};

void fun(std::stop_token stoken) {
    Writer() << "Start worker thread\n";
    while (!stoken.stop_requested()) {
        Writer() << "is sleeping and need stop\n";
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    Writer() << "End worker thread\n";
}

int main() {
    Writer() << ">>>Main End\n";

    {
        std::jthread       jth(fun);
        std::stop_callback callback(jth.get_stop_token(),
                                    [] { Writer() << "$$$Stop callback executed\n"; });

        std::this_thread::sleep_for(std::chrono::seconds(3));
        Writer() << ">>>Main before request\n";
        jth.request_stop();
        Writer() << ">>>Main after request\n";
    }

    Writer() << ">>>Main End\n";
}
19312>>>Main End
6856Start worker thread
6856is sleeping and need stop
6856is sleeping and need stop
6856is sleeping and need stop
19312>>>Main before request
6856is sleeping and need stop
19312$$$Stop callback executed
19312>>>Main after request
6856End worker thread
19312>>>Main End



END

关注我,学习更多C/C++,算法,计算机知识

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

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

相关文章

springboot3以及上版本引入RocketMQTemplate显示could not be found.

1. 问题所在 springboot3以及上版本引入RocketMQTemplate显示could not be found&#xff1f; 在springboot3时&#xff0c;直接通过依赖来注入RocketMQTemplate会报错&#xff0c;会显示没有这个对象。 这是因为在Springboot3以前的版本&#xff0c;自动装配是通过读取所有jar…

Docker容器化技术(docker-compose安装部署案例)

docker-compose编排工具 安装docker-compose [rootservice ~]# systemctl stop firewalld [rootservice ~]# setenforce 0 [rootservice ~]# systemctl start docker[rootservice ~]# wget https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-…

xinput1_3.dll丢失如何修复,xinput1_3.dll的安装修复教程分享

在Windows操作系统环境下&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到xinput13.dll”。由于xinput1_3.dll是微软DirectX SDK的一部分&#xff0c;主要用于支持游戏手柄和其他外部设备的输入功能&#xff0c;缺失这一动态链接库文件可能导致某些依赖…

高顿咨询如何用国产CRM实现经验决策到数据决策的跨越

编者按 近日&#xff0c;Salesforce 移动应用在中国大陆苹果应用商店的下架&#xff0c;预示着今年CRM国产化替代即将迎来高潮。CRM作为距离业务最近的软件&#xff0c;被公认为是企业数字化转型、高质量发展的核心系统之一。“企业如何选择一款真正满足自身业务需求的本土化C…

邮件客户端 Thunderbird 简单配置

1. 基本情况介绍 原来使用的邮箱客户端是 Office 365 自带的 Outlook 365切换原因&#xff1a;新装电脑&#xff0c;发现原 Outlook 中的账号信息无法迁移&#xff0c;需要耗费大量时间手动配置邮箱使用的邮箱&#xff1a;微软 O365 邮箱、qq 邮箱、163 邮箱、公司私有邮箱 …

stable diffusion webui ubuntu 安装

1.git clone 下来 GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UIStable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.https://github.com/AUTOMATIC1111/stable-diffus…

阻止默认行为 e.preventDefault()搭配passive:false才有效

正确情况 如果想阻止默认行为,那么 e.preventDefault()搭配passive:false才是正解 document.addEventListener(touchmove,(e)>{ e.preventDefault() console.log(123,123);},{passive:false}) 如果搭配 passive:false,则会报警告 e.preventDefault()搭配passive:true会报…

FREERTOS软件定时器

FreeRTOS 也提供了定时器功能&#xff0c;不过是软件定时器&#xff0c;软件定时器的精度肯定没有硬件定时器那么高&#xff0c;但是对于普通的精度要求不高的周期性处理的任务来说够了。当MCU的硬件定时器不够的时候就可以考虑使用 FreeRTOS 的软件定时器。 软件定时器允许设置…

HCIP【静态路由综合实验练习】

目录 实验要求&#xff1a; 实验过程&#xff1a; 一&#xff1a;首先设计实验 二&#xff1a;IP地址的划分&#xff08;基于192.168.1.0/24&#xff09; 在ensp中对路由器的相关命令进行配置&#xff1a; 三&#xff1a;配IP地址 &#xff08;1&#xff09;首先给所有设…

conda创建环境网络报错解决办法

文章目录 一、报错示例&#xff1a;二、解决办法&#xff1a;2.1 查看配置 conda config --show-sources2.2 修改文件 /home/XXXX/.condarc 一、报错示例&#xff1a; UnavailableInvalidChannel: HTTP 404 NOT FOUND for channel nvidia <http://mirrors.tuna.tsinghua.ed…

uniapp 开发微信小程序 出现启用组件按需注入问题如何解决

问题描述 在使用uniapp 开发微信小程序&#xff0c;进行上架发布时 代码质量栏 出现启用组件按需注入问题。 虽然现实代码上传成功&#xff0c;但是作为一个吹毛求疵的老猿人&#xff0c;肯定是无法容忍的。那么如何解决呢&#xff1f; 问题解决方案 在uniapp端&#xff0c…

[HackMyVM] Quick

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

QT增加线程函数步骤流程

在使用线程的时候&#xff0c;不仅要关注线程开启的时机&#xff0c;同时还要关注线程安全退出&#xff0c;这样才能保证程序的健壮性&#xff0c;如果线程开启的较多&#xff0c;且开启关闭比较频繁&#xff0c;建议使用线程池来处理。开启线程有三种方式&#xff1a;第一种C的…

房屋租赁系统|基于JSP技术+ Mysql+Java+ B/S结构的房屋租赁系统设计与实现(可运行源码+数据库+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;ssm&#xff0c;springboot的平台设计与实现项目系统开发资源&#xff08;可…

Milvus 社区在线寻找「北辰使者」!!!

Milvus 社区的朋友们&#xff0c;大家好&#xff0c;欢迎来到 Milvus 北极星计划发布现场&#xff01; 熟悉我们的朋友都知道&#xff0c;Milvus 起源于一种学名叫“赤鸢”的鸟类&#xff0c;鸟类飞行的方向判断依靠星星、太阳、磁场&#xff0c;而北极星在人类历史上长期被视为…

24考研数学史上最难!25该怎么学?

25考研的千万不要被以前的真题卷给蒙蔽了双眼&#xff0c;现在考研的和以前真的不一样了 做过24年考研数学试卷的&#xff0c;应该都有一个感受&#xff0c;平时训练的好像都没用上。这是为啥啊。 其实是因为&#xff0c;现在的考研数学更加注重基础的考察&#xff0c;并且计…

sqllab第二十八关通关笔记(附带28a)

知识点&#xff1a; union select 整体过滤 union all select 替换where id(输入)空格 过滤了&#xff0c;使用%09代替 经过不断的测试&#xff0c;发现原始语句为 where id(输入) 构造payload:id1)and%091(1 成功回显出了相关的信息 好&#xff0c;尝试进行错误注入 构造…

git 安装、创建仓库、常用命令、克隆下载、上传项目、删除分支 -- 一篇文章总结

一、git安装 1、git安装地址&#xff1a;https://git-scm.com/downloads 2、选择操作系统 3、安装自己系统对应的操作位数 4、等待下载完&#xff0c;一路next安装就可以了 5、安装完成后&#xff0c;在任意文件夹点击右键&#xff0c;看到下图说明安装成功 二、创建仓库 1…

集成电路:基本概念、工作原理与分类

随着科技的飞速发展&#xff0c;集成电路已经成为现代电子信息产业的基础。那么&#xff0c;什么是集成电路呢&#xff1f;本文将为您介绍集成电路的基本概念、工作原理以及分类等基础知识。 一、集成电路的基本概念 集成电路&#xff08;Integrated Circuit&#xff0c;简称I…

Mysql数据库基本操作与简单管理

目录 一、MySQL数据库基本操作 1、SQL的分类 2、SQL语言的书写规范 3、数据库对象的命名 4、SQL的语句分类 5、查看帮助信息 6、查看&#xff0c;修改字符集 二、管理MySQL数据库 1、查看数据库的结构 1.1查看数据库 1.2查看数据库中的表 1.2.1方法一&#xff1a; …