在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);
}