【Cocos2d-x】C++自定义线程安全消息管理

【Cocos2d-x】C++自定义线程安全消息管理

一、背景

由于Cocos2d-x本身的NotificationCenter是没有进行线程安全处理的,所以当我们在Cocos2d-x里面使用多线程进行消息同步的时候,会出现问题。那么为了解决这个问题,我们只需要进行线程安全锁定即可。

为了不修改源码,我模仿NotificationCenter,自定义了一个消息管理。


二、思路

首先,我们定义一个消息体的数据类型Message。他里面存储有消息名称Name,消息处理函数,消息目标,消息内容。

然后,我们定义一个消息管理类。他里面有消息容器。去容纳每一个消息。管理类对外暴漏的接口只有添加消息和发送消息。具体内容需要自己实现。

最后,将消息容器每次操作加锁即可。一个可以重复利用的,多线消息处理机制就完成了。


三、代码

头文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**************************************************************
  * Copyright (c) 2014-11-12 by real.Xm  
  * Blog Address:http://blog.csdn.net/q229827701
  * Email: 229827701@qq.com
  **************************************************************/
 
#ifndef __XMESSAGE__H
#define __XMESSAGE__H
 
 
#include "cocos2d.h"
class  XMessage;
class  CC_DLL MessageMsg :  public  cocos2d::Ref
{
public :
     MessageMsg();
     virtual  ~MessageMsg();
     static  MessageMsg* getInstance();
     bool  addObserver( const  std::string &msgName,cocos2d::Ref* target,
         cocos2d::SEL_CallFuncO selector,cocos2d::Ref* msgContent = nullptr);
     bool  postMessage( const  std::string &msgName,cocos2d::Ref* msgContent);
     bool  removeObserverByName( const  std::string &msgName,cocos2d::Ref* target = nullptr);
     bool  removeAllObservers(cocos2d::Ref* target);
protected
     XMessage* getMessageByName( const  std::string &msgName)  const ;
private :
     //message container
     cocos2d::Vector<XMessage*> _msgContainer; 
};
class  CC_DLL XMessage:  public  cocos2d::Ref
{
public :
     XMessage( const  std::string &msgName,cocos2d::Ref* target,
         cocos2d::SEL_CallFuncO selector,cocos2d::Ref* msgContent);
     ~XMessage();
     void  handerMessage(cocos2d::Ref* msgContent);
CC_SYNTHESIZE_READONLY(std::string,_msgName,MessageName); //message name
CC_SYNTHESIZE_READONLY(cocos2d::Ref*,_target,Target);    //target
CC_SYNTHESIZE_READONLY(cocos2d::SEL_CallFuncO,_selector,Selector); //function
CC_SYNTHESIZE_READONLY(cocos2d::Ref*,_msgContent,MessageConent); //function args
};
 
#endif // !_XMESSAGE_H

实现文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "XMessageManger.h"
 
std::mutex _ContainerMutex;
static  MessageMsg* _Manager = nullptr;
MessageMsg::MessageMsg()
{
 
}
 
MessageMsg::~MessageMsg()
{
     _msgContainer.clear();
}
 
MessageMsg* MessageMsg::getInstance()
{
     if  (!_Manager)
     {
         _Manager =  new  MessageMsg;
     }
     return  _Manager;
}
 
bool  MessageMsg::addObserver(  const  std::string &msgName,cocos2d::Ref* target,cocos2d::SEL_CallFuncO selector,cocos2d::Ref* msgContent  /*= nullptr*/  )
{
     if  (!getMessageByName(msgName))
     {
         auto msg =  new  XMessage(msgName,target,selector,msgContent);
         IF_NULL_RETURN_FALSE(msg);
         msg->autorelease();
         std::lock_guard<std::mutex> ul(_ContainerMutex);
         _msgContainer.pushBack(msg);
         return  true ;
     }
     return  false ;
}
 
bool  MessageMsg::postMessage(  const  std::string &msgName,cocos2d::Ref* msgContent )
{
     auto msg = getMessageByName(msgName);
     if  (msg)
     {
         msg->handerMessage(msgContent);
         return  true ;
     }
     return  false ;
}
 
XMessage* MessageMsg::getMessageByName(  const  std::string &msgName )  const
{
     std::lock_guard<std::mutex> ul(_ContainerMutex);
     for  (auto &msg : _msgContainer)
     {
         if  (msgName == msg->getMessageName())
         {
             return  msg;
         }
     }
     return  nullptr;
}
 
bool  MessageMsg::removeObserverByName(  const  std::string &msgName,cocos2d::Ref* target  /*= nullptr*/  )
{
     std::lock_guard<std::mutex> ul(_ContainerMutex);
     for  (auto &msg : _msgContainer)
     {
         if  (msgName == msg->getMessageName()
             &&(target == msg->getTarget()||!target))
         {
             _msgContainer.eraseObject(msg, true );
             return  true ;
         }
     }
     return  false ;
}
 
bool  MessageMsg::removeAllObservers( cocos2d::Ref* target )
{
     std::lock_guard<std::mutex> ul(_ContainerMutex);
     for  (auto &msg : _msgContainer)
     {
         if  (target == msg->getTarget())
         {
             _msgContainer.eraseObject(msg, true );
             return  true ;
         }
     }
     return  false ;
}
 
//
///   XMessage Class
/
 
XMessage::XMessage(  const  std::string &msgName,cocos2d::Ref* target,
                    cocos2d::SEL_CallFuncO selector,cocos2d::Ref* msgContent )
                    :_msgName(msgName),_target(target),_selector(selector),_msgContent(msgContent)
{
 
}
 
XMessage::~XMessage()
{
 
}
 
void  XMessage::handerMessage( cocos2d::Ref* msgContent )
{
     if  (_target)
     {
         if  (msgContent) {
             (_target->*_selector)(msgContent);
         else  {
             (_target->*_selector)(msgContent);
         }
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值