Message 및 Message Queue
17 Jul 2017 | C++11 Thread메세지(Message)와 메세지큐(MessageQueue)는 이벤트(Event)들을 한 곳에서 처리하거나 멀티 쓰레드(Multi-thread) 환경에서 쓰레드간 이벤트를 전달할 때 유용하게 사용됩니다.
C++로 구현된 메세지 및 메세지큐 예제입니다. 헤더 파일로만 이루어져 있어서 include 만으로 사용가능합니다. 또한 하단부에는 메세지와 메세지큐를 활용한 메세지 핸들러(Message Handler) 코드가 있습니다. 안드로이드의 핸들러(Handler)와 유사한 구조로 되어 있습니다.
Message.h
#ifndef SNOWDEER_MESSAGE_H #define SNOWDEER_MESSAGE_H class Message { public: Message(int _what) : what(_what), arg1(0), arg2(0) {} Message(int _what, int _arg1) : what(_what), arg1(_arg1), arg2(0) {} Message(int _what, int _arg1, int _arg2) : what(_what), arg1(_arg1), arg2(_arg2) {} virtual ~Message() {} int what; int arg1; int arg2; const static unsigned int MESSAGE_CLIENT_SOCKET_THREAD_CLOSED = 100; }; #endif //SNOWDEER_MESSAGE_H
MessageQueue.h
#ifndef SNOWDEER_MESSAGEQUEUE_H #define SNOWDEER_MESSAGEQUEUE_H #include <queue> #include <mutex> #include <condition_variable> using namespace std; template<class T> class MessageQueue { public: MessageQueue(void) : mQueue(), mMutex(), mCondition() { mIsLoop = true; } ~MessageQueue(void) { } void clear() { std::lock_guard<std::mutex> lock(mMutex); std::queue<T> emptyQueue; std::swap(mQueue, emptyQueue); } void enqueue(T t) { std::lock_guard<std::mutex> lock(mMutex); mQueue.push(t); mCondition.notify_one(); } void destory() { mIsLoop = false; mCondition.notify_one(); } T dequeue(void) { std::unique_lock<std::mutex> lock(mMutex); while((mIsLoop)&&(mQueue.empty())) { mCondition.wait(lock); } T val = mQueue.front(); mQueue.pop(); return val; } private: std::queue<T> mQueue; mutable std::mutex mMutex; std::condition_variable mCondition; bool mIsLoop; }; #endif //SNOWDEER_MESSAGEQUEUE_H
MessageHandler.h
#ifndef SNOWDEER_MESSAGE_H #define SNOWDEER_MESSAGE_H class Message { public: Message(int _what) : what(_what), arg1(0), arg2(0) {} Message(int _what, int _arg1) : what(_what), arg1(_arg1), arg2(0) {} Message(int _what, int _arg1, int _arg2) : what(_what), arg1(_arg1), arg2(_arg2) {} virtual ~Message() {} int what; int arg1; int arg2; const static unsigned int MESSAGE_CLIENT_SOCKET_THREAD_CLOSED = 100; }; #endif //SNOWDEER_MESSAGE_H
MessageHandler.cc
#include "MessageHandler.h" MessageHandler::MessageHandler() { mIsRunning = false; } MessageHandler::~MessageHandler() {} void MessageHandler::start() { mIsRunning = true; mLooper = std::thread(&MessageHandler::loop, this); } void MessageHandler::stop() { mIsRunning = false; if(mLooper.joinable()) { mLooper.join(); } clear(); mMessageQueue.destory(); } void MessageHandler::sendMessage(shared_ptr<Message> message) { mMessageQueue.enqueue(message); } void MessageHandler::clear() { mMessageQueue.clear(); } void MessageHandler::loop() { while(mIsRunning) { shared_ptr<Message> message = mMessageQueue.dequeue(); if(mIsRunning == false) { break; } switch(message->what) { case 1: break; case 2: break; } } }