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

适配qnx和linux平台的线程管理类封装

概述

封装代码仓库: https://gitee.com/liudegui/my_thread

尝试封装一个基于C++11的多线程控制与调度类,适配QNX和Linux平台,且代码符合Misra标准。它提供了以下主要功能:

  • 线程的创建与销毁管理。
  • 线程的优先级调度。
  • 线程的CPU亲和性设置。
  • 线程的等待与唤醒机制。

类的结构及主要成员函数如下:

  • 构造函数与析构函数:负责初始化线程相关参数,并在析构时确保线程安全退出。
  • thread_start():启动线程,创建指定数量的线程实例。
  • thread_shutdown():关闭线程,释放资源并等待所有线程退出。
  • timed_wait():线程的超时等待机制,防止线程无限等待。
  • set_self_thread_priority():设置当前线程的优先级。

实现细节

MyThread类内部实现主要涉及以下几个方面:

  • 使用std::thread来创建线程实例。
  • 利用std::mutex和std::condition_variable来实现线程同步。
  • 使用pthread库来设置线程的优先级和CPU亲和性。
/**
* my_thread.h
*/#ifndef UTILS_MY_THREAD_H_
#define UTILS_MY_THREAD_H_#include <atomic>
#include <cstdint>
#include <functional>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include <condition_variable>
#include <memory>namespace MyTest {
class MyThread {public:explicit MyThread(const std::string& in_name, int32_t in_priority, uint32_t in_worker_num,const std::function<void()> in_func, int32_t in_cpusetsize, const cpu_set_t*const in_cpuset);~MyThread();void thread_start();void thread_shutdown();bool has_shutdown() const {return is_shutdown_;}void timed_wait(uint32_t useconds);static void set_self_thread_priority(int32_t in_priority);private:static void my_thread_func_(MyThread* thread_ins);private:std::string thread_name_;int32_t thread_priority_;uint32_t thread_worker_num_;std::vector<std::shared_ptr<std::thread>> my_threads_;std::function<void()> func_main_;int32_t thread_cpusetsize_;const cpu_set_t* thread_cpuset_ = nullptr;std::mutex thread_mutex_;std::condition_variable thread_cond_;bool is_shutdown_;
};}  // namespace MyTest#endif  // UTILS_MY_THREAD_H_
/**
* my_thread.cpp
*/#include "my_thread.h"#include <ctime>
#include <sstream>
#ifndef _QNX_
#include <sys/syscall.h>
#endif
#include <sys/types.h>
#include "fake_log.h"namespace MyTest {MyThread::MyThread(const std::string& in_name, int32_t in_priority, uint32_t in_worker_num,const std::function<void()> in_func, int32_t in_cpusetsize, const cpu_set_t* const in_cpuset): thread_name_(in_name),thread_priority_(in_priority),thread_worker_num_(in_worker_num),func_main_(in_func),thread_cpusetsize_(in_cpusetsize),thread_cpuset_(in_cpuset),is_shutdown_(true) {
}MyThread::~MyThread() {if (!is_shutdown_) {thread_shutdown();}
}void MyThread::my_thread_func_(MyThread* thread_ins) {if (thread_ins == nullptr) {MY_LOG_ERROR("thread_ins is nullptr");} else {
#ifndef _QNX_if ((thread_ins->thread_cpuset_ != nullptr) && (thread_ins->thread_cpusetsize_ > 0)) {const pthread_t tid = pthread_self();const auto np_return =pthread_setaffinity_np(tid, static_cast<size_t>(thread_ins->thread_cpusetsize_), thread_ins->thread_cpuset_);if (np_return != 0) {MY_LOG_ERROR("pthread_setaffinity_np failed. return=%d", np_return);}}
#else// qnx ...
#endifstd::stringstream thread_id_stream;thread_id_stream << std::this_thread::get_id();MY_LOG_INFO("thread %s starts. pid=%s target_priority=%d", thread_ins->thread_name_.c_str(),thread_id_stream.str().c_str(), thread_ins->thread_priority_);MyThread::set_self_thread_priority(thread_ins->thread_priority_);try {thread_ins->func_main_();} catch (...) {MY_LOG_ERROR("Exception occurred in thread %s", thread_ins->thread_name_.c_str());}}
}void MyThread::thread_start() {std::lock_guard<std::mutex> lck(thread_mutex_);is_shutdown_ = false;my_threads_.resize(thread_worker_num_);uint32_t thread_idx = 0;for (; thread_idx < thread_worker_num_; thread_idx++) {my_threads_[thread_idx] = std::make_shared<std::thread>(my_thread_func_, this);}
}void MyThread::thread_shutdown() {std::lock_guard<std::mutex> lck(thread_mutex_);if (!is_shutdown_) {is_shutdown_ = true;thread_cond_.notify_all();for (const auto& my_t : my_threads_) {if (my_t->joinable()) {my_t->join();}}}
}void MyThread::timed_wait(uint32_t useconds) {std::unique_lock<std::mutex> lck(thread_mutex_);const auto timeout_val = std::chrono::microseconds(useconds);do {const auto return_val = thread_cond_.wait_for(lck, timeout_val);if (return_val == std::cv_status::timeout) {MY_LOG_ERROR("thread timed_wait timeout");}} while (false);
}void MyThread::set_self_thread_priority(int32_t in_priority) {bool go_on = true;struct sched_param params;struct sched_param current_params;int32_t set_policy{0};int32_t current_policy{0};const pthread_t this_thread = pthread_self();int32_t status_ret = pthread_getschedparam(this_thread, &current_policy, &current_params);if (status_ret != 0) {MY_LOG_ERROR("getschedparam %d", status_ret);go_on = false;} else {MY_LOG_DEBUG("thread current priority is %d (%d), target is %d", current_params.sched_priority, current_policy,in_priority);  // MY_LOG_TRACEif (in_priority == 0) {go_on = false;} else if (in_priority > 0) {set_policy = SCHED_FIFO;params.sched_priority = current_params.sched_priority + in_priority;} else {set_policy = SCHED_IDLE;params.sched_priority = 0;}}if (go_on) {if (params.sched_priority > 99) {params.sched_priority = 99;}if (params.sched_priority < 0) {params.sched_priority = 0;}status_ret = pthread_setschedparam(this_thread, set_policy, &params);if (status_ret != 0) {MY_LOG_WARN("setschedparam(%d)", params.sched_priority);go_on = false;}}if (go_on) {status_ret = pthread_getschedparam(this_thread, &current_policy, &current_params);if (status_ret != 0) {MY_LOG_ERROR("getschedparam 2 %d", status_ret);} else {if (current_params.sched_priority != params.sched_priority) {MY_LOG_ERROR("current priority=%d (%d), target is %d", current_params.sched_priority, current_policy,params.sched_priority);} else {MY_LOG_INFO("set thread priority to %d (%d)", current_params.sched_priority, current_policy);}}}
}}  // namespace MyTest

测试代码

#include "my_thread.h"#include <chrono>
#include <iostream>
#include <string>namespace MyTest {
static void worker_function() {std::this_thread::sleep_for(std::chrono::milliseconds(100));std::cout << "Thread ID: " << std::this_thread::get_id() << " is working." << std::endl;
}
}  // namespace MyTestint32_t main() {int32_t main_res{0};try {const uint32_t num_threads = 4;cpu_set_t cpuset1;CPU_ZERO(&cpuset1);CPU_SET(0, &cpuset1);std::vector<std::shared_ptr<MyTest::MyThread>> test_threads;uint32_t thread_idx = 0;for (; thread_idx < num_threads; ++thread_idx) {const std::string thread_name1 = std::string("Thread_") + std::to_string(thread_idx);const std::shared_ptr<MyTest::MyThread> my_t = std::make_shared<MyTest::MyThread>(thread_name1, 1, 1, MyTest::worker_function, sizeof(cpuset1), &cpuset1);test_threads.push_back(my_t);}for (const auto& my_t : test_threads) {my_t->thread_start();}std::this_thread::sleep_for(std::chrono::seconds(2));for (const auto& my_t : test_threads) {my_t->thread_shutdown();}for (const auto& my_t : test_threads) {while (!my_t->has_shutdown()) {// std::this_thread::yield();my_t->timed_wait(100);}}std::cout << "All threads have been shutdown." << std::endl;} catch (...) {std::cerr << "Exception occurred" << std::endl;main_res = 1;}return main_res;
}

相关文章:

适配qnx和linux平台的线程管理类封装

概述 封装代码仓库&#xff1a; https://gitee.com/liudegui/my_thread 尝试封装一个基于C11的多线程控制与调度类&#xff0c;适配QNX和Linux平台&#xff0c;且代码符合Misra标准。它提供了以下主要功能&#xff1a; 线程的创建与销毁管理。线程的优先级调度。线程的CPU亲…...

【信息系统项目管理师】复习~第十五章

15.项目风险管理 每个项目都存在两个层面上的风险&#xff1a;①每个项目都有会影响项目达成目标的单个风险&#xff1b;②由单个风险和不确定性的其他来源联合导致的整体项目风险。项目风险会对项目目标产生负面或正面的影响&#xff0c;也就是风险与机会。项目风险管理旨在利…...

ARM单片机实现流水灯(GD32)

根据上图可知使用的引脚分别是PA8,PE6,PF6流水灯功能的实现要分别初始化这几个引脚 流水灯实现 编写流水灯代码 LED.C #include "gd32f30x.h" // Device header #include "Delay.h" // 初始化LED灯 void LED_Init(void){// 使能RCU时钟…...

操作系统基础之磁盘

概述 基本概念 磁盘有正反两个盘面&#xff0c;每个盘面有多个同心圆&#xff0c;每个同心圆是一个磁道&#xff0c;每个同心圆又被划分为多个扇区&#xff0c;数据就被存在扇区中。 磁头首先寻找到对应磁道&#xff0c;然后等到磁盘进行周期旋转到指定的扇区&#xff0c;才…...

【Unity Shader入门精要 第6章】基础光照(一)

1. 什么是光照模型 光照原理 在真实世界中&#xff0c;我们能够看到物体&#xff0c;是由于眼睛接收到了来自观察目标的光。这里面包括两种情况&#xff1a;一部分是观察目标本身发出的光&#xff08;自发光&#xff09;直接进入我们的眼睛&#xff0c;另一部分是其他物体&am…...

JavaEE概述 + Maven

文章目录 一、JavaEE 概述二、工具 --- Maven2.1 Maven功能 仓库 坐标2.2 Maven之项目构建2.3 Maven之依赖管理 三、插件 --- Maven Helper 一、JavaEE 概述 Java SE、JavaEE&#xff1a; Java SE&#xff1a;指Java标准版&#xff0c;适用于各行各业&#xff0c;主要是Java…...

python把png转成jpg

在Python中&#xff0c;你可以使用PIL&#xff08;Python Imaging Library&#xff0c;也称为Pillow&#xff09;库来读取PNG图片并将其转换为JPG格式。下面是一个简单的示例代码&#xff1a; from PIL import Image# 打开PNG图片 png_image Image.open(input.png)# 保存为JP…...

信息系统架构基本概念及发展_2.信息系统架构的定义

1.几种架构的定义 信息系统架构仍在不断发展中&#xff0c;还没有形成一个公认的定义&#xff0c;这里举出几个定义。 定义1&#xff1a;软件或计算机系统的信息系统架构是该系统的一个&#xff08;或多个&#xff09;结构&#xff0c;而结构由软件元素、元素的外部可见…...

ctfshow SSRF 351-358

做题前,需要先学习关于ssrf漏洞的相关知识 小注意: 当使用 file_get_contents() 函数访问远程 URL 时&#xff0c;它会尝试获取该 URL 指向的资源的内容&#xff0c;并将内容以字符串的形式返回。 如果 b.php 文件是一个 PHP 文件&#xff0c;它包含的内容取决于该 PHP 文件…...

优化学习方法,事半功倍

学习&#xff0c;是人一生中必不可少的过程。在学习的道路上&#xff0c;我们会遇到各种各样的挑战和困难&#xff0c;但只要我们能够发现并优化适合自己的学习方法&#xff0c;就能事半功倍&#xff0c;取得更好的成绩。 首先&#xff0c;要充分了解自己的学习方式和习惯。每个…...

Spring STOMP-开启STOMP

通过Spring框架的spring-messaging和spring-websocket模块&#xff0c;提供了对WebSocket上STOMP的支持。一但你添加了这些依赖项&#xff0c;你就可以像下面这个示例一样&#xff0c;通过WebSocket公开一个STOMP端点&#xff1a; import org.springframework.web.socket.conf…...

Python 开发 框架安全:Django SQL注入漏洞测试.(CVE-2021-35042)

什么是 Django 框架 Django 是一个用 Python 编写的 Web 应用程序框架。它提供了许多工具和库&#xff0c;使得开发 Web 应用程序变得更加容易和高效。Django 遵循了“MTV”&#xff08;模型-模板-视图&#xff09;的设计模式&#xff0c;将应用程序的不同组件分离开来&#x…...

《Python编程从入门到实践》day25

# 昨日知识点回顾 如何创建多行外星人 碰撞结束游戏 创建game_stats.py跟踪统计信息 # 今日知识点学习 第14章 记分 14.1 添加Play按钮 14.1.1 创建Button类 import pygame.font# button.py class Button:def __init__(self, ai_game, msg):"""初始化按钮…...

Unity 性能优化之光照优化(七)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、测试目的一、实时光源是什么&#xff1f;二、开始测试1.场景中只有一个光照的数值情况2.添加4个点光源后4.结果 总结 前言 实时光源数量越多&#x…...

C语言 | Leetcode C语言题解之第84题柱状图中最大的矩形

题目&#xff1a; 题解&#xff1a; int largestRectangleArea(int* heights, int heightsSize) {int st[heightsSize];int p[2];p[0]-1,p[1]heightsSize;int size0,result0;st[size]0;for(int i1;i<heightsSize;i){ while(size!0&&heights[i]<heights[st[size-1…...

AI办公自动化-用kimi批量重命名Word文档

文件夹里面有很多个word文档&#xff0c;标题里面都含有零代码编程&#xff0c;现在想将其替换为AI办公自动化。 在kimichat中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个编写Python脚本的任务&#xff0c;具体步骤如下&#xff1a; 打开文件夹&am…...

Golang 并发 Mutex 互斥锁的使用

Golang 并发 Mutex 互斥锁的使用 1. 初始化 func TestMutex(t *testing.T) {mu01 : sync.Mutex{}var mu02 sync.Mutex }两种方式都ok 2. Mutex使用 计数器统计&#xff0c;多个协程同时对同一个变量进行 代码示例 var mu sync.Mutex var counter intfunc TestMutexAdd(t…...

20232906 2023-2024-2 《网络与系统攻防技术》第九次作业

20232906 2023-2024-2 《网络与系统攻防技术》第九次作业 1.实验内容 本次实践的对象是一个名为pwn1的linux可执行文件。 该程序正常执行流程是&#xff1a;main调用foo函数,foo函数会简单回显任何用户输入的字符串。 该程序同时包含另一个代码片段&#xff0c;getShell&am…...

常见的十二种软件架构

常用的软件架构有多种&#xff0c;以下是一些主要的软件架构风格&#xff1a; 单体架构&#xff08;Monolithic Architecture&#xff09;&#xff1a; 描述&#xff1a;所有功能都集中在一个应用或系统中&#xff0c;易于开发和部署&#xff0c;但随着系统增长&#xff0c;可能…...

数据库出现死锁的解决方法参考

死锁引起的原因一般是多个用户并发访问数据库导致的问题&#xff0c;或是因为某个进程挂死以后资源未释放导致的。通过onstat –p可查看deadlks项大于0即表示历史总计死锁次数。对于被锁的表进行操作的时候会出现-143 ISAM error: deadlock detected的错误。当其他会话访问此表…...

HCIP-Datacom-ARST自选题库_01_防火墙【6道题】

一、单选题 1.在防火墙域间安全策略中&#xff0c;请问以下哪一项的数据流不是Outbound方向的? 从Trust区域到DMZ区域的数据流 从Trust区域到Untrust区域的数据流 从Trust区域到Local区域的数据流 从DMZ区域到Untrust区域的数据流 2.如果防火墙域间没有配置安全策路&…...

力扣/leetcode383.比特位记数

题目描述 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 示例 代码思路 第一种方法 最简单的方法就是&#xff0c;遍历然后使用python自带的bin()方法直接…...

react18【系列实用教程】useEffect —— 副作用操作 (2024最新版)

什么是副作用操作&#xff1f; useEffect 用于编写由渲染本身引起的对接组件外部的操作&#xff08;官方称呼为&#xff1a;副作用操作&#xff09; 以下情况会触发页面渲染 初次加载页面&#xff08;组的挂载&#xff09;响应式变量发生变化&#xff0c;触发页面根据新值重新…...

Excel 分组汇总后删除明细

有 Excel 数据如下所示&#xff1a; IDCriteria1Criteria2Criteria3Criteria4101210271239312381236123171826182918239182120182147 需要按 ID 分组汇总其余列&#xff0c;结果如下&#xff1a; IDCriteria1Criteria2Criteria3Criteria410121027123932561826939267 解法及简…...

docker runc升级1.1.12

上传runc-1.1.12制品至中控机 874e970eaa932a97de9888344ae08f24 runc.arm64 将所有节点的runc文件备份 所有节点(包括master+node) vim host [all] 10.1.0.183 ansible_password=Bigdata@Ksyun123 ansible_user=root ansible_port=22 10.1.0.249 ansible_password=Bigdata…...

C++接口:构建模块化与可扩展的软件架构

目录标题 1. 接口的定义与作用2. 抽象类作为接口3. 接口的设计原则4. 示例&#xff1a;使用接口实现多态5. 拓展&#xff1a;接口和类的区别6. 结论 在C编程中&#xff0c;接口是一种重要的设计模式&#xff0c;它定义了一组方法&#xff0c;这些方法可以被不同的类实现。接口在…...

【讲解下目标追踪】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…...

实时Linux对EtherCAT工业自动化协议的支持

在自动化技术和工业控制领域&#xff0c;实时通信网络的重要性不断增长。EtherCAT&#xff08;Ethernet for Control Automation Technology&#xff09;作为一种高效的工业以太网通信协议&#xff0c;因其出色的性能和灵活性而广受欢迎。而实时Linux作为影响最为广泛的开源实时…...

ViLT 浅析

ViLT 浅析 论文链接&#xff1a;ViLT 文章目录 ViLT 浅析创新点网络结构总结 创新点 本文先分析了4种不同类型的Vision-and-Language Pretraining(VLP) 其中每个矩形的高表示相对计算量大小&#xff0c;VE、TE和MI分别是visual embedding、text embedding和modality interact…...

7-117 死亡隧道

小毛驴要回家了,凭借着刚从老毛驴处学到的闪烁魔法,小毛驴信心满满地出发了。这一次它来到了另一条死亡隧道口,但是,小毛驴不知道死亡威胁随时存在,因为它所打算穿过的这条死亡隧道即将于T秒时间后坍塌。 已知小毛驴行走的速度是每秒17米,而小毛驴拥有的闪烁法术可以使它…...