C++实现仿安卓线程Handler、Message、Looper的功能
在java开发中,习惯使用Handler、Message来处理同步,比如对相机的操作(open、setParamters、start、stop、clost)全部抛到同一个线程处理,防止并发操作导致异常,这样保留给外部的统一接口就是安全的,无论外部哪些线程来调用,最终到控制模块都是在同一线程处理相机操作。这里提供一个C++实现的Handler Message封装,可以实现类似安卓那样的接口;
Handler类封装:
#ifndef _CPP_THREADHANDLER_H
#define _CPP_THREADHANDLER_H#include <algorithm>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <thread>
#include "Message.h"class ThreadHandler {public:using TimePoint_t = std::chrono::steady_clock::time_point;using Clock_t = std::chrono::steady_clock;using MillisDuration_t = std::chrono::milliseconds;using Task = std::function<void(const Message& msg)>;ThreadHandler() : _stoped(false) { initLoop(); }~ThreadHandler() {_stoped = true;_cond.notify_all();_looper.join();}void setName(const std::string n) { this->name = n; }bool sendEmptyMessageDelay(int what, long delay_millis) {if (what < 0 || delay_millis < 0)return false;Message msg(what, delay_millis);std::unique_lock<std::mutex> lock(_queue_lock);_msg_list.push_back(msg);_msg_list.sort(std::less<Message>());_cond.notify_all();return true;}bool sendEmptyMessageDelay(int what) {return sendEmptyMessageDelay(what, 0);}bool postDelay(std::function<void()>&& f, long delay_millis) {if (f == nullptr || delay_millis < 0) {return false;}std::unique_lock<std::mutex> lock(_queue_lock);Message msg(0, delay_millis);msg.onRun(std::move(f));_msg_list.push_back(msg);_msg_list.sort(std::less<Message>());_cond.notify_all();return true;}bool post(std::function<void()>&& f) { return postDelay(std::move(f), 0); }void removeMessages(int what) {if (what < 0)return;std::unique_lock<std::mutex> lock(_queue_lock);if (!_msg_list.empty())_msg_list.remove_if([what](const Message& m) { return m.what == what; });}void removeAlls() {std::unique_lock<std::mutex> lock(_queue_lock);if (!_msg_list.empty())_msg_list.clear();printf("ThreadHandler::removeAlls name: %s",name.c_str());}void stop() {_stoped = true;_cond.notify_all();printf("ThreadHandler::stop name: %s", name.c_str());}void handleMessage(Task&& cb) { _callback = cb; }private:void dispatchMessage(const Message& msg) const {if (msg.task != nullptr) {msg.task();} else {if (msg.what < 0 || _callback == nullptr)return;_callback(msg);}}void initLoop() {_looper = std::thread([this]() {while (true) {Message msg;bool isFired = false;{std::unique_lock<std::mutex> lock(_queue_lock);if (_msg_list.empty()) {_cond.wait(lock, [this] {return _stoped || !_msg_list.empty();});} else {auto front = _msg_list.front();// 如果要when 大于 当前时间,则休眠;否则继续往下执行if (front.when > Clock_t::now()) {if (front.when > Clock_t::now() + maxSleepTime) {printf("ThreadHandler::initLoop time too long name: %s, when: ""%s ,now: %s , maxSleepTime: %s",name.c_str(),std::to_string(std::chrono::duration_cast<std::chrono::seconds>(front.when.time_since_epoch()).count()).c_str(),std::to_string(std::chrono::duration_cast<std::chrono::seconds>(Clock_t::now().time_since_epoch()).count()).c_str(),std::to_string(std::chrono::duration_cast<std::chrono::seconds>(maxSleepTime).count()).c_str());}_cond.wait_until(lock, front.when, [this] {return _stoped || (!_msg_list.empty() &&_msg_list.front().when <= Clock_t::now());});}}if (!_stoped && _msg_list.empty())continue;if (_stoped) {_msg_list.clear();return;}// List的头结点的时间小于等于当前时间,则执行头结点任务if (_msg_list.front().when <= Clock_t::now()) {msg = std::move(_msg_list.front());_msg_list.pop_front();isFired = true;}}if (isFired) {dispatchMessage(msg);}}});}bool _stoped;std::string name;std::list<Message> _msg_list;std::mutex _queue_lock;std::condition_variable _cond;std::thread _looper;Task _callback;std::chrono::minutes maxSleepTime{4};
};#endif // _CPP_THREADHANDLER_H
Message实现类:
#ifndef _CPP_MESSAGE_H
#define _CPP_MESSAGE_H
#include <chrono>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <thread>class Message {public:using TimePoint_t = std::chrono::steady_clock::time_point;using Clock_t = std::chrono::steady_clock;using MillisDuration_t = std::chrono::milliseconds;int what;int m_arg1;int m_arg2;std::function<void()> task;TimePoint_t when;Message() : Message(-1, 0) {}Message(int what) : Message(what, 0) {}Message(int what, long delayMillis): what(what), when(Clock_t::now() + MillisDuration_t(delayMillis)) {task = nullptr;}Message(const Message& msg): what(msg.what), task(msg.task), when(msg.when) {}Message(Message&& msg) : what(msg.what), task(msg.task), when(msg.when) {}~Message() {}Message& operator=(const Message& msg) {this->what = msg.what;this->when = msg.when;this->task = msg.task;return *this;}Message& operator=(Message&& msg) {this->what = msg.what;this->when = msg.when;this->task = std::move(msg.task);return *this;}void setWhen(long delayMillis) {when = Clock_t::now() + MillisDuration_t(delayMillis);}void onRun(std::function<void()>&& f) { this->task = f; }bool operator>(const Message& msg) const { return (this->when > msg.when); }bool operator<(const Message& msg) const { return (this->when < msg.when); }bool operator==(const Message& msg) const {return (this->what == msg.what) && (this->task != nullptr) &&(msg.task != nullptr);}bool operator==(int what) const { return (this->what == what); }
};#endif // _CPP_MESSAGE_H
使用方法:
//构造函数或类初始化中设置如下
mHandler.setName("classATh");
mHandler.handleMessage([&](const Message& msg) { handleMessage(msg); });
void classATh::handleMessage(const Message& msg) {
if (msg.what == MSG_CODE_QUERY_DEVICE_INFO) {
//
} else if (msg.what == MSG_CODE_TRADE_INIT) {
//
} else if (msg.what == MSG_CODE_DEVICE_HEART_BEAT) {
heartBeat();
}
}
void classATh::startHearBeat() {
mHandler.removeMessages(MSG_CODE_DEVICE_HEART_BEAT);
mHandler.sendEmptyMessageDelay(MSG_CODE_DEVICE_HEART_BEAT, 60 * 1000);
}
相关文章:
C++实现仿安卓线程Handler、Message、Looper的功能
在java开发中,习惯使用Handler、Message来处理同步,比如对相机的操作(open、setParamters、start、stop、clost)全部抛到同一个线程处理,防止并发操作导致异常,这样保留给外部的统一接口就是安全的,无论外部哪些线程来…...
构建安全的用户登录API:从请求验证到JWT令牌生成
构建安全的用户登录API:从请求验证到JWT令牌生成 为了实现这个后端POST /api/users/login端点,我们可以使用Node.js和Express框架,并结合一些常用的库如jsonwebtoken、bcrypt和express-validator来处理验证和密码校验。下面是一个完整的示例…...
状态模式:封装对象状态并改变行为的设计模式
1. 引言 在软件开发中,某些对象的行为会随着其内部状态的变化而变化。传统的实现方式可能需要使用大量的条件语句,导致代码复杂且难以维护。状态模式(State Pattern)提供了一种有效的方法,通过将状态行为封装在状态类…...
备战“双11”丨AI+物流:你的快递会有什么变化?
背景 在中国,每天有数以亿计的包裹在运输,尤其在电商促销季如“双十一”、“618”期间,快递量更是激增。快递物流行业面临人员短缺、配送效率低下和物流承载能力有限等问题。快瞳科技提供的AI识别解决方案通过智能化手段提高工作效率和配送准…...
理解为什么要有C++设计模式
什么时设计模式? 每一个模式描述了一个在我们周围不断重复的问题以及该问题的解决方案的核心,这样,就能一次有一次地使用该方案,而不必做重复劳动。 如何解决复杂性? 分解:人们面对复杂性有一个常见的做法…...
模式匹配类型
一、匹配常量 在scala中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等 def describeConst(x:Any):String x match {case "str" > "匹配字符串"case > "匹配字符&…...
每天10个vue面试题(七)
1、Vue如何监听页面url中hash变化? 监听 $route 的变化:在Vue中,你可以使用watch属性来监听$route的变化。当路由发生变化时,会执行相应的处理函数。使用 window.location.hash:直接读取window.location.hash的值。这…...
如何在Linux系统中使用Apache HTTP Server
如何在Linux系统中使用Apache HTTP Server Apache简介 安装Apache 在Debian/Ubuntu系统中安装 在CentOS/RHEL系统中安装 启动Apache服务 验证Apache是否正在运行 访问Apache默认页面 配置Apache虚拟主机 创建虚拟主机配置文件 示例虚拟主机配置 创建网站根目录 准备静态网站内…...
C++基于opencv的视频质量检测--画面冻结检测
文章目录 0.引言1. 原始代码分析2. 优化方案3. 优化后的代码4. 代码详细解读 0.引言 视频质量画面冻结检测已在C基于opencv4的视频质量检测中有所介绍,本文将详细介绍其优化版本。 1. 原始代码分析 图像抖动检测的原始代码: bool ScreenFreezeDetect…...
Day22 opencv图像预处理
图像预处理 在计算机视觉和图像处理领域,图像预处理是一个重要的步骤,它能够提高后续处理(如特征提取、目标检测等)的准确性和效率。OpenCV 提供了许多图像预处理的函数和方法,常见的操作包括图像空间转换、图像大小调…...
QT中的定时器与计时器
目录 QTimer QTimer 的替代方案 API QElapsedTimer API 笔者写Qt的时候经常遇到需要定时完成任务的情况。举个例子:我写串口通信程序的时候需要定时向下位机发送数据。或者是定时任务周期性出发(更新时间等) 在Qt中,有两个非…...
国内AI大模型学习平台
据不完全统计,目前,国内有几大AI大模型学习平台可供选择: 1.昇思大模型平台:这是一个集算法选型、创意分享、模型实验和大模型在线体验于一体的AI学习与实践社区。 2.魔搭社区:提供AI模型、数据集和应用的开发与探索平…...
曹操出行借助 ApsaraMQ for Kafka Serverless 提升效率,成本节省超 20%
本文整理于 2024 年云栖大会主题演讲《云消息队列 ApsaraMQ Serverless 演进》,杭州优行科技有限公司消息中间件负责人王智洋分享 ApsaraMQ for Kafka Serverless 助力曹操出行实现成本优化和效率提升的实践经验。 曹操出行:科技驱动共享出行未来 曹操…...
深入理解数据库的三范式
数据库设计中的范式(Normal Form)是用于规范数据存储结构、消除冗余以及保证数据一致性的重要原则。范式的概念有多种层次,常用的前三种称为第一范式(1NF)、第二范式(2NF)和第三范式(…...
P11233 [CSP-S 2024] 染色
P11233 [CSP-S 2024] 染色 难度:提高/省选-。 考点:DP。 题意: 给定 n n n 个数 A i A_i Ai,对 A i A_i Ai 进行染色,只有两种颜色。设 C C C 为 A A A 染色后的数组。 如果 A i A_i Ai 左侧没有预期同…...
图传推流学习(敬请期待)
图传推流简介 1.RTSP、RTP与RTCP2.搭建rtsp服务器(资源下载)3.搭建rtsp服务器(搭建过程) 1.RTSP、RTP与RTCP RTSP(Real Time Streaming Protocol)、RTP(Real-time Transport Protocol࿰…...
【JavaGuide】十大经典排序算法总结
冒泡排序 算法步骤 不断的两两比较,这样当前最大的元素总是会排在最后面。所以称为冒泡。 图解算法 代码实现 public static int[] bubbleSort(int[] arr) {// i是排好了几个数for (int i 1; i < arr.length; i) {// flag标记当前循环是否调整了顺序,…...
程序中怎样用最简单方法实现写excel文档
很多开发语言都能找到excel文档读写的库,但是在资源极其受限的环境下开发,引入这些库会带来兼容性问题。因为一个小功能引入一堆库,我始终觉得划不来。看到有项目引用的jar包有一百多个,看着头麻,根本搞不清谁依赖谁。…...
《机器学习与人类学习:比较、融合与未来展望》
《机器学习与人类学习:比较、融合与未来展望》 一、引言二、机器学习的概念与发展(一)机器学习的定义与分类(二)机器学习的发展历程(三)机器学习的应用领域 三、人类学习的本质与过程࿰…...
Mysql 8.4.3LTS 的离线部署
文章目录 一、部署环境资源配置 二、下载地址版本选择 三、部署详情1. 上传安装包2. 解压软件包3. 安装mysql3.3.1 创建mysql用户与用户组3.3.2 授权安装文件夹3.3.3 安装libaio依赖 (坑)ubuntu24.04 中关于libaio的坑 3.3.4 初始化Mysql数据库3.3.5 编辑…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
【技巧】dify前端源代码修改第一弹-增加tab页
回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码,在知识库增加一个tab页"HELLO WORLD",完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...
