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 编辑…...
行业研究报告怎么选:看清咨询公司的“真本事”
一、为什么大家都在找“靠谱的行业研究报告”这几年,不论是创业公司做战略决策,还是大型企业布局新业务,几乎都有一个共识——决策要有数据、有研究、有趋势支撑。于是,“行业研究报告”成了商业决策的必备工具,但市场…...
PlugY终极指南:暗黑破坏神2单机模式完全解放方案
PlugY终极指南:暗黑破坏神2单机模式完全解放方案 【免费下载链接】PlugY PlugY, The Survival Kit - Plug-in for Diablo II Lord of Destruction 项目地址: https://gitcode.com/gh_mirrors/pl/PlugY 还在为暗黑破坏神2单机模式的储物箱空间不足而烦恼吗&am…...
GEE引擎封挂实战:从M2参数到RunGate网关的完整配置指南
GEE引擎封挂实战:从M2参数到RunGate网关的完整配置指南 在游戏运营过程中,外挂问题一直是困扰开发者和运营者的顽疾。对于使用GEE引擎的游戏服务器来说,如何有效防范和打击外挂行为,维护游戏公平性,是每个技术团队必须…...
告别GitHub下载卡顿:手把手教你配置Electron国内镜像(npmrc文件详解)
告别Electron下载困境:深度解析.npmrc配置与国内镜像实战指南 每次执行npm install electron时,看着进度条卡在node install.js阶段一动不动,或是突然蹦出RequestError: connect ETIMEDOUT的红色报错——这种体验对于国内开发者来说再熟悉不过…...
2.2.2.2 使用Spark单机版环境
本次实战深入探索Spark单机版环境的核心功能。首先运行SparkPi示例程序计算圆周率,验证集群计算能力;随后启动spark-shell进入交互式环境,完成等差数列求和、九九乘法表打印等基础任务。重点通过Scala代码操作RDD,演示了从文本文件…...
Qwen3.5-4B-Claude-Opus一文详解:GGUF量化模型在低延迟推理场景下的优势
Qwen3.5-4B-Claude-Opus一文详解:GGUF量化模型在低延迟推理场景下的优势 1. 模型概述 Qwen3.5-4B-Claude-4.6-Opus-Reasoning-Distilled-GGUF是基于Qwen3.5-4B架构的推理蒸馏模型,特别强化了结构化分析、分步骤回答以及代码与逻辑类问题的处理能力。该…...
5个实战场景掌握DeepSeek-Coder-V2:打造企业级私有化AI编程助手
5个实战场景掌握DeepSeek-Coder-V2:打造企业级私有化AI编程助手 【免费下载链接】DeepSeek-Coder-V2 DeepSeek-Coder-V2: Breaking the Barrier of Closed-Source Models in Code Intelligence 项目地址: https://gitcode.com/GitHub_Trending/de/DeepSeek-Coder-…...
新手友好:借助快马AI零基础实现openclaw101官网登录功能入门教程
今天想和大家分享一个特别适合编程新手的实践项目——如何用最简单的方式实现一个网站登录功能。作为一个刚入门的前端学习者,我发现登录功能看似简单,其实包含了很多核心知识点。通过InsCode(快马)平台,我们可以轻松获得一个完整可运行的登录…...
《算法竞赛从入门到国奖》算法基础:动态规划-最长子序列
💡Yupureki:个人主页 ✨个人专栏:《C》 《算法》《Linux系统编程》《高并发内存池》《MySQL数据库》 《个人在线OJ平台》 🌸Yupureki🌸的简介: 目录 1. 最长上升子序列 算法原理 代码示例 2. 合唱队形 算法原理 代码示例 3. 最长公共…...
QQ音乐加密文件完整解码指南:qmcdump终极教程
QQ音乐加密文件完整解码指南:qmcdump终极教程 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 还在为QQ音乐下…...
