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_BEGIN
static 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