C++ 模仿Android實現Handler機制
阿新 • • 發佈:2019-01-25
前言:
一直使用android的Handler,感覺非常好用,但是當我使用C++程式設計時,想使用Android Handler一樣的程式設計模式,竟不知如何下手,網上找了很久,都沒找到具體的實現,能搜尋到MFC中使用handler,但是一直不搞windows的開發,也不曉得上哪兒去弄,也可能是我找的不夠多吧。這個Handler已經嚴重的影響了我,沒有它左右不舒服。這兩天沉下心來自己寫了一個,省的自己去找了,以後肯定還能用到,最好有網友也做了類似實現,我可以借鑑下以提升自己。
程式碼參考Android Handler,有興趣的朋友可以去看看Android 裡面的實現。
Handler.h
#pragma once #ifndef HANDLER_H #define HANDLER_H #include <chrono> #include <map> #include <mutex> #include <vector> #include <thread> #include "Message.h" /* * Handler will run in it's own thread, you don't want to care about it. * Message will be proccess by the Handler. Two ways to add your task to the Handler. * 1. send message to the handler * 2. post the task(Function) to handler */ class Handler{ public: Handler(); virtual ~Handler(); bool sendMessageAtTime(Message& msg, long uptimeMillis); bool sendMessage(Message& msg); bool sendEmptyMessage(int what); bool sendEmptyMessage(int what, long uptimeMillis); bool post(Message::Function f); bool postAtTime(Message::Function f, long uptimeMillis); void removeMessages(int what); void removeCallbackAndMessages(); void stopSafty(bool stopSafty); bool isQuiting(); virtual void handleMessage(Message& msg); void dispatchMessage(Message& msg); /* * for msgQueue sorted when insert, * ascending order */ template<class T> class ValComp { public: bool operator()(const T& t1,const T& t2) const { return (t1 < t2); } }; private: std::vector<Message> msg_Q; std::mutex queue_mutex; std::condition_variable condition; std::thread looper; bool stop; bool stopWhenEmpty; }; #endif
Handler.cpp
#include <chrono> #include <algorithm> #include <iostream> #include "Handler.h" #include "Message.h" #define LOGENTER (std::cout << "This is FUNCTION " << __func__<< std::endl) Handler::Handler():stop(false),stopWhenEmpty(false){ looper = std::thread( [this](){ for(;;) { Message msg; { std::unique_lock<std::mutex> lock(this->queue_mutex); if(this->msg_Q.empty()){ this->condition.wait(lock, [this]{ return this->stop || this->stopWhenEmpty || !this->msg_Q.empty();}); }else{ this->condition.wait_until(lock, this->msg_Q.back().when, [this]{ return this->stop || this->stopWhenEmpty || !this->msg_Q.empty(); }); } if(this->stopWhenEmpty && this->msg_Q.empty()) return; if(stop){ msg_Q.clear(); return; } msg = std::move(msg_Q.back()); msg_Q.pop_back(); } this->dispatchMessage(msg); } }); } Handler::~Handler(){ { std::unique_lock<std::mutex> lock(queue_mutex); stop = true; } condition.notify_all(); looper.join(); msg_Q.clear(); } void Handler::handleMessage(Message& msg){ std::cout << "IN Handler " << __func__<< " what:" << msg.m_what << std::endl; } bool Handler::sendMessageAtTime(Message& msg, long uptimeMillis){ if(uptimeMillis < 0 ) return false; msg.setWhen(uptimeMillis); std::unique_lock<std::mutex> lock(queue_mutex); auto i = std::find(msg_Q.begin(),msg_Q.end(),msg); msg_Q.erase(i); msg_Q.push_back(msg); std::sort(msg_Q.begin(), msg_Q.end(),std::greater<Message>()); condition.notify_one(); return true; } bool Handler::sendMessage(Message& msg){ return false; std::unique_lock<std::mutex> lock(queue_mutex); auto i = find(msg_Q.begin(),msg_Q.end(),msg); if(i != msg_Q.end()) msg_Q.erase(i); msg_Q.push_back(msg); std::sort(msg_Q.begin(), msg_Q.end(),std::greater<Message>()); condition.notify_one(); return true; } bool Handler::sendEmptyMessage(int what){ return sendEmptyMessage(what ,0); } bool Handler::sendEmptyMessage(int what,long uptimeMillis){ if(what < 0 || uptimeMillis < 0) return false; Message msg(what); msg.setWhen(uptimeMillis); std::unique_lock<std::mutex> lock(queue_mutex); std::vector<Message>::iterator i = find(msg_Q.begin(),msg_Q.end(),msg); if (i != msg_Q.end()){ msg_Q.erase(i); } msg_Q.push_back(msg); // std::sort(msg_Q.begin(), msg_Q.end(),ValComp<Message>()); // 跟進時間進行降序排列 std::sort(msg_Q.begin(), msg_Q.end(),std::greater<Message>()); condition.notify_one(); return true; } bool Handler::post(Message::Function f){ return postAtTime(f,0); } bool Handler::postAtTime(Message::Function f, long uptimeMillis){ if(f == nullptr || uptimeMillis < 0){ return false; } std::unique_lock<std::mutex> lock(queue_mutex); Message msg; msg.setWhen(uptimeMillis); msg.setFunction(f); msg_Q.push_back(msg); std::sort(msg_Q.begin(), msg_Q.end(),std::greater<Message>()); return true; } void Handler::removeMessages(int what){ if(what < 0) return; std::unique_lock<std::mutex> lock(queue_mutex); auto i = find(msg_Q.begin(),msg_Q.end(),what); if (i != msg_Q.end()){ msg_Q.erase(i); } condition.notify_one(); } void Handler::removeCallbackAndMessages(){ std::unique_lock<std::mutex> lock(queue_mutex); msg_Q.clear(); } void Handler::stopSafty(bool stopSafty){ std::unique_lock<std::mutex> lock(queue_mutex); if(stopSafty){ stopWhenEmpty = true; }else{ stop = true; } } bool Handler::isQuiting(){ std::unique_lock<std::mutex> lock(queue_mutex); if(stop || stopWhenEmpty) return true; return false; } void Handler::dispatchMessage(Message& msg){ if(msg.task != nullptr){ msg.task(); }else{ if(msg.m_what < 0) return; handleMessage(msg); } }
使用:
class myHandler : public Handler{
virtual void handleMessage(Message& msg) override {
Handler::handleMessage(msg);
switch(msg.m_what){
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
default:
break;
}
cout << "IN myHandler case: " << msg.m_what << endl;
}
};
int main(int argc, char **argv)
{
cout << "IN main" << endl;
myHandler hdlr;
for(int i = 0; i < 6; i++){
hdlr.sendEmptyMessage(i, 100 * i);
}
hdlr.postAtTime([](){
cout << "IN POST call back" << endl;
}, 230);
hdlr.stopSafty(true); //停止handler,在停止前處理完所有訊息
while(true){
std::this_thread::sleep_for(std::chrono::seconds(100000));
}
return 1;
}
這裡只帖出Handler的實現,還有個配套的Message實現,感興趣的童鞋自己去下面連結檢視吧。
程式碼連結:https://github.com/feekia/EventServer