#include "precompile.h" #include #include "framework/cpp/msgqueue.h" #include "app.h" namespace f8 { struct MsgQueueNode { struct list_head entry; MsgHandleFunc func; }; class MsgQueueImp { public: int curr_im_msgid = 10000; std::map msg_handlers; std::map custom_free_funcs; ~MsgQueueImp() { for (auto& pair : msg_handlers) { while (!list_empty(&pair.second)) { MsgQueue::Instance()->RemoveCallBack(pair.second.next); } } } void ProcessMsg(int msgid, const a8::XParams& param) { auto itr = msg_handlers.find(msgid); if (itr != msg_handlers.end()) { list_head* head = &itr->second; struct MsgQueueNode *node = nullptr; struct MsgQueueNode *tmp = nullptr; list_for_each_entry_safe(node, tmp, head, entry) { node->func(param); } } } CallBackHandle RegisterCallBack(int msgid, MsgHandleFunc handle_func) { MsgQueueNode* node = new MsgQueueNode(); INIT_LIST_HEAD(&node->entry); node->func = handle_func; auto itr = msg_handlers.find(msgid); if (itr == msg_handlers.end()) { msg_handlers[msgid] = list_head(); itr = msg_handlers.find(msgid); assert(itr != msg_handlers.end()); INIT_LIST_HEAD(&itr->second); } list_add_tail(&node->entry, &itr->second); return &node->entry; } }; void MsgQueue::Init() { imp_ = new MsgQueueImp(); } void MsgQueue::UnInit() { delete imp_; imp_ = nullptr; } void MsgQueue::SendMsg(int msgid, a8::XParams param) { imp_->ProcessMsg(msgid, param); } void MsgQueue::PostMsg(int msgid, a8::XParams param) { param._sys_field = msgid; a8::Timer::Instance()->AddDeadLineTimer(0, param, [] (const a8::XParams& param) { MsgQueue::Instance()->imp_->ProcessMsg(param._sys_field, param); }); } void MsgQueue::AddDelayMsg(int msgid, a8::XParams param, int milli_seconds) { param._sys_field = msgid; a8::Timer::Instance()->AddDeadLineTimer(milli_seconds, param, [] (const a8::XParams& param) { MsgQueue::Instance()->imp_->ProcessMsg(param._sys_field, param); }); } void MsgQueue::RemoveCallBack(CallBackHandle handle) { list_head* head = handle; MsgQueueNode* node = list_entry(head, struct MsgQueueNode, entry); list_del_init(&node->entry); delete node; } CallBackHandle MsgQueue::RegisterCallBack(int msgid, MsgHandleFunc handle_func) { return imp_->RegisterCallBack(msgid, handle_func); } int MsgQueue::AllocIMMsgId(CustomIMMsgFreeFunc free_func) { int custom_im_msgid = ++imp_->curr_im_msgid; if (free_func) { imp_->custom_free_funcs[custom_im_msgid] = free_func; } return custom_im_msgid; } void MsgQueue::FreeCustomIMMsg(a8::XParams& param) { auto itr = imp_->custom_free_funcs.find(param.sender.GetInt()); if (itr != imp_->custom_free_funcs.end()) { itr->second(param); } } void MsgQueue::ProcessMsg(int msgid, const a8::XParams& param) { imp_->ProcessMsg(msgid, param); } void MsgQueue::PostMsg_r(int msgid, a8::XParams param) { a8::XParams* p = new a8::XParams(); param.DeepCopy(*p); App::Instance()->AddIMMsg(f8::IM_SysMsgQueue, a8::XParams().SetSender(msgid).SetParam1((void*)p)); } }