f8/cpp/msgqueue.cc
aozhiwei a09180d909 1
2019-07-08 17:22:41 +08:00

142 lines
4.1 KiB
C++

#include "precompile.h"
#include <a8/timer.h>
#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<int, list_head> msg_handlers;
std::map<int, CustomIMMsgFreeFunc*> 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));
}
}