cocos2dx C++自定义线程安全消息管理

一、背景

由于cocos2dx本身的NotificationCenter是没有进行线程安全处理的,所以当我们在cocos2dx里面使用多线程进行消息同步的时候,

会出现问题。那么为了解决这个问题,我们只需要进行线程安全锁定即可。

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

二、思路

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

然后,我们定义一个消息管理类。他里面有消息容器。去容纳每一个消息。

管理类对外暴漏的接口只有添加消息和发送消息。具体内容需要自己实现。

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

三、代码

头文件:

/**************************************************************
 * Copyright (c) 2014-11-12 by real.Xm
 * Blog Address:	http://blog.csdn.net/q229827701
 * Email: [email protected]
 **************************************************************/

#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

实现文件

#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);
		}
	}
}

四、申明

本文原创,为尊重原创,转载时请注明出处。

http://blog.csdn.net/q229827701/article/details/41042147

时间: 2024-10-10 01:04:58

cocos2dx C++自定义线程安全消息管理的相关文章

Android线程管理之ThreadPoolExecutor自定义线程池(三)

前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己来自定义一个线程池,今天来学习一下ThreadPoolExecutor,然后结合使用场景定义一个按照线程优先级来执行的任务的线程池. ThreadPoolExecutor ThreadPoolExecutor线程池用于管理线程任务队列.若干个线程. 1.)ThreadPoolExecutor构造函数

看我是如何处理自定义线程模型---java

看过我之前文章的园友可能知道我是做游戏开发,我的很多思路和出发点是按照游戏思路来处理的,所以和web的话可能会有冲突,不相符合. 来说说为啥我要自定义线程模型呢? 按照我做的mmorpg或者mmoarpg游戏划分,线程被划分为,主线程,全局同步线程,聊天线程,组队线程,地图线程,以及地图消息分发派送线程等: 一些列,都需要根据我的划分,以及数据流向做控制. 游戏服务器,主要要做的事情,肯定是接受玩家的 命令请求 -> 相应的操作 -> 返回结果: 在服务器端所有的消息都会注册到消息管理器里,然

.NET组件程序设计之线程、并发管理(二)

.Net组件程序设计之线程.并发管理(二) 2.同步线程 手动同步 监视器 互斥 可等待事件 同步线程 所有的.NET组件都支持在多线程的环境中运行,可以被多个线程并发访问,如果没有线程同步,这样的后果是当多个线程同时访问 对象状态时,对象的状态可能被破坏,造成不一致性..NET提供了两种方法来避免这样的问题,使得我们设计的组件更加健壮. 第一种是自动同步,让你使用一个属性来修饰组件,这样就可以把组件交给.NET了,同步的事情也就交给了.NET. 第二种是手动同步,这是让你使用.NET提供的同步

6)Linux程序设计入门--消息管理

6)Linux程序设计入门--消息管理 前言:Linux下的进程通信(IPC) Linux下的进程通信(IPC) POSIX无名信号量 System V信号量 System V消息队列 System V共享内存 1.POSIX无名信号量 如果你学习过操作系统,那么肯定熟悉PV操作了.PV操作是原子 操作.也就是操作是不可以中断的,在一定的时间内,只能够有一个进程的代码在CPU上面 执行.在系统当中,有时候为了顺利的使用和保护共享资源,大家提出了信号的概念. 假设 我们要使用一台打印机,如果在同一

Android 自定义线程池的实战

前言:在上一篇文章中我们讲到了AsyncTask的基本使用.AsyncTask的封装.AsyncTask 的串行/并行线程队列.自定义线程池.线程池的快速创建方式. 对线程池不了解的同学可以先看 Android AsyncTask 深度理解.简单封装.任务队列分析.自定义线程池 ------------------------------------------------------------------------------------------------------- 1.Exec

Java 多线程 自定义线程辅助

之前的文章我介绍了C#版本的多线程和自定义线程处理器. 接下来我们来看看Java版本的呢 java 的线程和C#的线程有点区别,java的线程没有是否是后台线程一说,具体原因是java的线程是jvm的c++代码模拟线程,而C#的线程也是C++模拟线程.但是区别在于C#的线程会基于系统的线程. C# 的 Thread.IsBackground; 这里唯一的区别在于,C#开启线程如果是非后台线程即便是你关闭了程序,如果不是强制退出进程的情况下.线程还会继续运行,知道垃圾回收机制强制回收.如果设置了后

使用自定义线程池优化EchoServer

在上一篇文章中http://www.cnblogs.com/gosaint/p/8494423.html 我自定义了线程池ThreadPool.现在在我的EchoServer中使用自定义线程池去负责和客户端的通讯,代码如下所示: package com.asiaInfo.caozg.ch_03.threadPool; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; imp

微信公众号开发C#系列-6、消息管理-普通消息接受处理

1.概述 通过前面章节的学习,我们已经对微信的开发有了基本的掌握与熟悉,基本可以上手做复杂的应用了.本篇我们将详细讲解微信消息管理中普通消息的接收与处理.当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上.接收普通消息微信官方文档参考:接收普通消息文档API 消息接收后,就有一个处理或回复的过程,单单发送消息了没有响应也是不人性化的,下面我们就对接收到微信各类型消息分别讲解处理的方法. 2.消息接收 当普通微信用户向公众账号发消息时,微信服务器会先接收

池化技术——自定义线程池

目录 池化技术--自定义线程池 1.为什么要使用线程池? 1.1.池化技术的特点: 1.2.线程池的好处: 1.3.如何自定义一个线程池 2.三大方法 2.1.单个线程的线程池方法 2.2.固定的线程池的大小的方法 2.3.可伸缩的线程池的方法 2.4.完整的测试代码为: 3.为什么要自定义线程池?三大方法创建线程池的弊端分析 4.七大参数 5.如何手动的去创建一个线程池 6.四种拒绝策略 6.1.会抛出异常的拒绝策略 6.2.哪来的去哪里拒绝策略 6.3.丢掉任务拒绝策略 6.4.尝试竞争拒绝