这个系列以本人游戏开发的实例来详细讲解Cocos2d-x,本篇阐述内存的自动释放池。因为在上一篇我们学习了引用计数和自动释放的大概流程,其中略过了自动释放池,这里简单述说。
前面提到CCObject的autorelease函数
CCObject* CCObject::autorelease(void) { CCPoolManager::sharedPoolManager()->addObject(this); return this; }
这里的sharedPoolManager()函数表明CCPoolManager是个单例类。
题外话:cocos2d-x里面大量的用到了单例模式,每个单例类都有个明显的标志,就是它的实例获取函数,从命名规则上看都是sharedxxx()形式。
跟进这个addObject函数
void CCPoolManager::addObject(CCObject* pObject) { getCurReleasePool()->addObject(pObject); }
这里就到了CCPoolManager,来看下这个类
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(); friend class CCAutoreleasePool; };这里可以看到它维护一个自动释放池CCAutoreleasePool,还有个CCArray变量,是个栈结构,来管理自动释放池。
看下实现:
#include "CCAutoreleasePool.h" #include "ccMacros.h" NS_CC_BEGIN // 自动释放池管理员实例 static CCPoolManager* s_pPoolManager = NULL; CCAutoreleasePool::CCAutoreleasePool(void) { m_pManagedObjectArray = new CCArray(); // 自动释放的对象放在这个Array里面 m_pManagedObjectArray->init(); } CCAutoreleasePool::~CCAutoreleasePool(void) { CC_SAFE_DELETE(m_pManagedObjectArray); } void CCAutoreleasePool::addObject(CCObject* pObject) { m_pManagedObjectArray->addObject(pObject);// 实质上的添加函数,加到对象管理数组里面 CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");//断言 ++(pObject->m_uAutoReleaseCount); 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->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; --(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() { finalize(); // we only release the last autorelease pool here m_pCurReleasePool = 0; m_pReleasePoolStack->removeObjectAtIndex(0); CC_SAFE_DELETE(m_pReleasePoolStack); } void CCPoolManager::finalize() { 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() //管理员的push方法,将对象池栈压栈。当前对象池为NULL时才调用push函数 { CCAutoreleasePool* pPool = new CCAutoreleasePool(); //ref = 1 m_pCurReleasePool = pPool; m_pReleasePoolStack->addObject(pPool); //ref = 2 pPool->release(); //ref = 1 } void CCPoolManager::pop() // 管理员的pop方法,将对象池栈弹栈,其实就是释放对象 { 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();// 对象池由一个栈维护。当前对象池为空,则push一下,push函数会new一个对象池,然后添加到栈里 } CCAssert(m_pCurReleasePool, "current auto release pool should not be null"); return m_pCurReleasePool; } NS_CC_END
好了,就这些。
一个对象添加到自动释放池后在什么时机被释放,这里不写了。后面有机会再写。