首页 > 编程语言 >(C++20) jthread中stop_token的基础使用

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

时间:2024-03-20 18:32:41浏览次数:24  
标签:std include 20 Writer stop C++ token Main

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

文章目录

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++,算法,计算机知识

标签:std,include,20,Writer,stop,C++,token,Main
From: https://blog.csdn.net/CUBE_lotus/article/details/136885167

相关文章

  • 【合集】HZOI2024——冲刺NOIP2024
    前言喵喵于\(2024.3.18\)建立\(vjudge\)团队\(NOIP2024\),成员为全体\(HZOI2024\)初三现役人员,旗下三个板块的专题训练,分别为动态规划、图论、字符串,其中题目非紫即黑,存在少量蓝。并于\(2024.3.19\)成功关闭\(luogu\)。团队链接动态规划图论字符串接......
  • 2023年蓝桥杯省赛——棋盘
    目录题目链接:10.棋盘-蓝桥云课(lanqiao.cn)思路我的直接暴力思路代码实现前缀和思路前缀和:更多举例差分数组:更多举例前缀和与差分数组的关系如下代码实现 总结题目链接:10.棋盘-蓝桥云课(lanqiao.cn)思路我的直接暴力思路        我的这段Ja......
  • V208实现OnlyUpdate方式的OTA
    目录与多数沁恒家的MCU一样,V208的LD文件、启动文件使用的是公共文件,故不建议直接覆盖原路径中的文件,否则会导致其他工程的编译出问题。本文以MultiCentPeri例程作为原始例程,为其添加外置BLE固定库的OTA框架。步骤一:拷贝文件。完整复制一份MultiCentPeri工程的文件夹到同一目录......
  • c++简介
    C++(cplusplus)是一种计算机高级程序设计语言,由C语言扩展升级而产生[17],最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的......
  • 29个主要城市已有20城全面取消限购,下一个会是谁
       杭州去年10月发布的政策则把住房限购范围缩小为上城区、拱墅区、西湖区、滨江区四个主城核心区,其他区域解除限购。成都除了“5+2”地区(即四川天府新区直管区、成都高新区南部园区、锦江区、青羊区、金牛区、武侯区、成华区)继续实施住房限购,其他区域不再审核购房资格。......
  • C++面向对象整理(1)之初识类和对象
    C++面向对象整理(1)之初识类和对象注:整理一些突然学到的C++知识,随时mark一下例如:忘记的关键字用法,新关键字,新数据结构C++的类和对象C++面向对象整理(1)之初识类和对象一、类的定义1、类成员的访问权限2、类定义示例(1)类内定义(2)类外定义成员函数3、类对象(实例)的定义及......
  • Windows Server 2019 Oracle 19c Restore & Recovery
    RMAN>CONNECTTARGET/;RMAN>run{ SQL>shutdownimmediate; startupmountforce; startupmount; setuntiltime"to_date('2024-03-1905:36:58','yyyy-mm-ddhh24:mi:ss')"; restoredatabase; recoverdatabase; al......
  • 200. 岛屿数量c
    intvisit[300][300];voiddfs(char**grid,intm,intn,inti,intj){if(i>=m||j>=n)return;visit[i][j]=1;if(i+1<m&&grid[i+1][j]=='1'&&visit[i+1][j]==0){dfs(grid,m,n,i+1,j);}if(j......
  • 2024-03-20 闲话
    把上周四英语课的生词记录一下,文艺复兴一下。(不过最近草稿纸又用了大量了,应该会再做一些四级题把A4纸储备一下)rat&mouse一般认为rat是大老鼠,mouse的体型偏小mal-是一个前缀,表示“不好的”,比如malfunction动词表示“出故障”highcholestral高胆固醇的ulcer......
  • C++ static函数调用问题
    静态成员变量虽然在类中,但它并不是随对象的建立而分配空间的,也不是随对象的撤销而释放(一般的成员在对象建立时会分配空间,在对象撤销时会释放)。静态成员变量是在程序编译时分配空间,而在程序结束时释放空间。静态成员的定义和声明要加个关键static。静态成员可以通过双冒号来使用......