在java开发中,习惯使用Handler、Message来处理同步,比如对相机的操作(open、setParamters、start、stop、clost)全部抛到同一个线程处理,防止并发操作导致异常,这样保留给外部的统一接口就是安全的,无论外部哪些线程来调用,最终到控制模块都是在同一线程处理相机操作。这里提供一个C++实现的Handler Message封装,可以实现类似安卓那样的接口;
Handler类封装:
cpp
#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实现类:
cpp
#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);
}