cocos2dx 源码分析之 CCPoolManager
来源:互联网 发布:编程软件图标 编辑:程序博客网 时间:2024/05/16 17:59
cocos2dx 的对象自动管理池是一个很重要的内容,控制对象的自动释放,使得程序员不用被繁琐的内存申请和释放困扰。下面是 cocos2dx 相关的类。
CCAutoReleasePool.h
//防止头文件重复包含#ifndef __AUTORELEASEPOOL_H__#define __AUTORELEASEPOOL_H__#include "CCObject.h"#include "CCArray.h"NS_CC_BEGIN/** * @addtogroup base_nodes * @{ * @js NA * @lua NA */// CCAutoreleasePool 继承自 CCObject class CC_DLL CCAutoreleasePool : public CCObject{ // 对象自动管理池,本质就是一个数组,控制对象的添加和释放 CCArray* m_pManagedObjectArray; public: // 构造函数 CCAutoreleasePool(void); // 析构函数 ~CCAutoreleasePool(void); // 往 CCAarry 中增加对象 void addObject(CCObject *pObject); // 从 CCAarry 中删除对象 void removeObject(CCObject *pObject); // 清空 CCAarry void clear();};/** * @js NA * @lua NA */class CC_DLL CCPoolManager{ // 池管理器用来管理多个对象自动释放池 ,本质上也是通过一个数组来管理自动释放池 CCArray* m_pReleasePoolStack; // 当前正在操作的对象自动释放池 CCAutoreleasePool* m_pCurReleasePool; CCAutoreleasePool* getCurReleasePool();public: CCPoolManager(); ~CCPoolManager(); void finalize(); void push(); void pop(); void removeObject(CCObject* pObject); void addObject(CCObject* pObject); // 池管理器是一个单例模式 static CCPoolManager* sharedPoolManager(); // 清空池管理器 static void purgePoolManager(); // 申明友元类 CCAutoreleasePool friend class CCAutoreleasePool;};// end of base_nodes group/// @}NS_CC_END#endif //__AUTORELEASEPOOL_H__
CCAutoreleasePool.cpp
CCObject 有两个重要的属性,m_uReference (引用计数)和 m_uAutoReleaseCount (自动释放点)。
具体有什么作用呢。
其实你调用一次autorelease(),m_uAutoReleaseCount就会加+1,所以说你可以重复调用autorelease(),调用autorelease()的时候m_uReference曾经会被加1,但是最后还是被减回去了,所以m_uReference不会变,只是m_uAutoReleaseCount加了1。那么m_uAutoReleaseCount有什么用呢?他的意思就是:你交几个引用计数的点给自动回收的控制。懂什么意思吗?不懂的话举个例子:你手动retain()了一下m_uReference会增加1,这个值如果你不在最后手动调用release();那么对不起,他不会被回收,因为还有1。这个时候如果你调用了一个autorelease();那么他在还剩1个的时候,就会问m_uAutoReleaseCount说你等于几?如果你等于m_uReference,而且都大于0,那么也就是说剩下那几个点全是归自动回收的,那么好咧,我回收咯。然后就被回收了。
简单的说:如果你想被自动回收,那么你有三种选择。
1,不要retain.
2,retain几次,用完之后release几次 ,就好像new 和delete对应一样。这个的坏处就是你要时刻记得用完了的时候要release。
3,retain几次,就马上autorelease几次,这个的意思就是,这几个点就叫给你自动的管理了,当你的m_uReference和m_uAutoReleaseCount一样的时候,意思就是剩下的引用计数点都归自动管理池啦,他就回收掉了。好处就不用记得用完的时候release,而是retain后可以马上调用autorelease。
#include "CCAutoreleasePool.h"#include "ccMacros.h"// 命名空间 CC 作用域开始NS_CC_BEGINstatic CCPoolManager* s_pPoolManager = NULL;CCAutoreleasePool::CCAutoreleasePool(void){ // 为 m_pManagedObjectArray 申请内存 m_pManagedObjectArray = new CCArray(); // 申请内存为 1 m_pManagedObjectArray->init();}CCAutoreleasePool::~CCAutoreleasePool(void){ // 释放 m_pManagedObjectArray CC_SAFE_DELETE(m_pManagedObjectArray);}void CCAutoreleasePool::addObject(CCObject* pObject){ // 对象的引用计数 m_uReference 将 +1 // 如果 array 空间不够,则 double size m_pManagedObjectArray->addObject(pObject); // m_pManagedObjectArray 中的对象的引用计数必须大于1,要么 add 过,要么 Retain 过 CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1"); //调用 AutoRelease() 后,对象的自动释放计数点将增加 ++(pObject->m_uAutoReleaseCount); // 对象的m_uReference 将 -1, 如果对象的引用计数=0,则释放对象 pObject->release(); // no ref count, in this case autorelease pool added.}void CCAutoreleasePool::removeObject(CCObject* pObject){ for (unsigned int i = 0; i < pObject->m_uAutoReleaseCount; ++i) { // 从 m_pManagedObjectArray 中删除pObject , pObject 可能加了很多遍,所以要循环遍历 m_pManagedObjectArray->removeObject(pObject, false); }}void CCAutoreleasePool::clear(){ if(m_pManagedObjectArray->count() > 0) { //CCAutoreleasePool* pReleasePool;#ifdef _DEBUG int nIndex = m_pManagedObjectArray->count() - 1;#endif CCObject* pObj = NULL; // 删除所有对象 CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj) { if(!pObj) break; // 自动释放点减 1 --(pObj->m_uAutoReleaseCount); //(*it)->release(); //delete (*it);#ifdef _DEBUG nIndex--;#endif } m_pManagedObjectArray->removeAllObjects(); }}//--------------------------------------------------------------------//// CCPoolManager////--------------------------------------------------------------------// 单例模式CCPoolManager* CCPoolManager::sharedPoolManager(){ if (s_pPoolManager == NULL) { s_pPoolManager = new CCPoolManager(); } return s_pPoolManager;}void CCPoolManager::purgePoolManager(){ CC_SAFE_DELETE(s_pPoolManager);}CCPoolManager::CCPoolManager(){ // 申请内存 m_pReleasePoolStack = new CCArray(); m_pReleasePoolStack->init(); m_pCurReleasePool = 0;}CCPoolManager::~CCPoolManager(){ // 清空 m_pReleasePoolStack finalize(); // we only release the last autorelease pool here m_pCurReleasePool = 0; m_pReleasePoolStack->removeObjectAtIndex(0); CC_SAFE_DELETE(m_pReleasePoolStack);}void CCPoolManager::finalize(){ // 对 m_ReleasePoolStack 进行遍历释放 if(m_pReleasePoolStack->count() > 0) { //CCAutoreleasePool* pReleasePool; CCObject* pObj = NULL; CCARRAY_FOREACH(m_pReleasePoolStack, pObj) { if(!pObj) break; CCAutoreleasePool* pPool = (CCAutoreleasePool*)pObj; pPool->clear(); } }}void CCPoolManager::push(){ CCAutoreleasePool* pPool = new CCAutoreleasePool(); //ref = 1 // 往栈中增加对象 ,把当前自动释放池设为栈顶元素 m_pCurReleasePool = pPool; m_pReleasePoolStack->addObject(pPool); //ref = 2 pPool->release(); //ref = 1}void CCPoolManager::pop(){ // 当 m_pCurReleasePool == NULL 时,栈为空,则返回 if (! m_pCurReleasePool) { return; } // 如果不为空,则弹出栈顶元素,将当前自动释放池设置为弹出之后的栈顶元素 int nCount = m_pReleasePoolStack->count(); m_pCurReleasePool->clear(); if(nCount > 1) { m_pReleasePoolStack->removeObjectAtIndex(nCount-1);// if(nCount > 1)// {// m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);// return;// } m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2); } /*m_pCurReleasePool = NULL;*/}void CCPoolManager::removeObject(CCObject* pObject){ CCAssert(m_pCurReleasePool, "current auto release pool should not be null"); // 从当前的自动释放池中删除对象 m_pCurReleasePool->removeObject(pObject);}void CCPoolManager::addObject(CCObject* pObject){ // 从当前的自动释放池中增加对象 getCurReleasePool()->addObject(pObject);}CCAutoreleasePool* CCPoolManager::getCurReleasePool(){ if(!m_pCurReleasePool) { push(); } CCAssert(m_pCurReleasePool, "current auto release pool should not be null"); return m_pCurReleasePool;}// 命名空间 CC 作用域结束NS_CC_END
- cocos2dx 源码分析之 CCPoolManager
- cocos2dx 内存管理(3)---CCPoolManager浅析
- Cocos2dx源码分析之JumpBy的实现
- cocos2dx CCScrollView 源码分析
- cocos2dx-CCControlButton源码分析
- cocos2dx源码分析:ActionManager
- cocos2dx 源码分析 之Widget 头文件 (3.11.1)
- cocos2dx之商店源码
- cocos2dx源码之 选择器
- [cocos2dx]TestCpp框架源码分析
- cocos2dx源码分析:节点Node
- cocos2dx源码分析:定时器Scheduler
- cocos2dx源码分析:场景切换
- cocos2dx源码分析:层Layer
- cocos2dx源码分析:Texture2d创建
- cocos2dx源码之 CREATE_FUNC宏
- cocos2dx shader分析之CCGLProgram
- cocos2dx shader分析之CCGLProgram
- commons之函数式编程1_Predicate_TransformerJAVA138
- 动态sql例子
- What is 'lr_policy' in caffe?
- Android 反射接口Interface应用
- JavaScript 判断 DOM 何时加载完毕
- cocos2dx 源码分析之 CCPoolManager
- 栈和队列之LinekedList(双端队列)
- nltk function
- Mecv中遇见的ie兼容问题
- UIResponder
- Android编码规范
- vimrc
- 关于win10 64位安装 XP 32位注意事项
- 机器学习常见名词