原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38964637
之前学了那么多的内容,几乎所有的控件都要涉及内存管理类CCAutoreleasePool,所以这一次的学习笔记,我们一起来看看CCAutoreleasePool,先从CCObject的autorelease方法入手。
CCObject* CCObject::autorelease(void)
{
// 将当前对象添加到内存池中
CCPoolManager::sharedPoolManager()->addObject(this);
// 将当前对象设置为已被内存池管理
m_bManaged = true;
return this;
}autoRelease类并不复杂,由代码中的注释可以看出主要还是CCPoolManager的操作,也就是CCAutoreleasePool。
class CC_DLL CCAutoreleasePool : public CCObject
{
// 保存所有添加到释放池中的对象
// 注意CCArray内部是通过将对象retain 然后存储起来的,应用计数会增加1
CCArray* m_pManagedObjectArray;
public:
CCAutoreleasePool(void);
~CCAutoreleasePool(void);
// 将对象添加到自动释放池
void addObject(CCObject *pObject);
// 将对象从自动释放池中移除
void removeObject(CCObject *pObject);
// 将自动释放池中的对象释放掉
void clear();
};
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);
// 获取自动释放池管理者,整个程序代码中所有需要使用CCPoolManager的地方都通过这个函数获取
// 外部不应该自己new一个内存管理者来使用
static CCPoolManager* sharedPoolManager();
// 清理当前内存管理者,释放其中的自动释放池以及自动释放池中的所有对象
static void purgePoolManager();
friend class CCAutoreleasePool;
};// 静态成员变量,保存整个程序使用的自动释放池 管理者
static CCPoolManager* s_pPoolManager = NULL;
CCAutoreleasePool::CCAutoreleasePool(void)
{
//初始化队列,用以保存添加到池中的对象
m_pManagedObjectArray = new CCArray();
m_pManagedObjectArray->init();
}
CCAutoreleasePool::~CCAutoreleasePool(void)
{
CC_SAFE_DELETE(m_pManagedObjectArray);
}
// 将对象添加到自动释放池中
void CCAutoreleasePool::addObject(CCObject* pObject)
{
// 将对象retain 保存到队列中
m_pManagedObjectArray->addObject(pObject);
// 到这里,对象的应用计数最少应该是2
CCAssert(pObject->m_uReference > 1, "reference count should be greater than 1");
// 调用对象的release方法,将引用计数减1
// release方法在CCObject中实现,引用计数减1之后检查引用计数如果为0,则直接删除此对象
pObject->relearese(); // no ref count, in this case autorelease pool added.
}
void CCAutoreleasePool::removeObject(CCObject* pObject)
{
// 从自动释放池中移除对象,,使该对象不被自动释放池管理,当然也不会自动释放
// 第二个参数为false,,因为addObject被没有使引用计数增加,所有这里也不能使应用计数有变化
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_bManaged = false;
//(*it)->release();
//delete (*it);
#ifdef _DEBUG
nIndex--;
#endif
}
// 移除所有的在队列中的对象,依次调用所有对象的release方法
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()
{
// 向自动释放池队列中添加一个新的自动释放池,将新添加的自动释放池作为当前的
// 自动释放池使用
CCAutoreleasePool* pPool = new CCAutoreleasePool(); //ref = 1
m_pCurReleasePool = pPool;
m_pReleasePoolStack->addObject(pPool); //ref = 2
pPool->release(); //ref = 1
}
void CCPoolManager::pop()
{
// 清理自动释放池队列,只剩下队列中的第一个自动释放池
// 剩下的这个自动释放池中的对象也要清理掉
// 这个函数便是自动释放池管理者,实现自动释放池内对象的实现了
if (! m_pCurReleasePool)
{
return;
}
int nCount = m_pReleasePoolStack->count();
// 清理当前的自动释放池
m_pCurReleasePool->clear();
if(nCount > 1)
{
// 如果自动释放池队列中有超过一个自动释放池
// 将末端的自动释放池清理并移除
m_pReleasePoolStack->removeObjectAtIndex(nCount-1);
m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2);
}
}
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()
{
// 获取当前的自动释放池
// 如果当前的自动释放池为空,说明自动释放池队列中也为空
// 通过push方法,添加新的自动释放池
if(!m_pCurReleasePool)
{
push();
}
CCAssert(m_pCurReleasePool, "current auto release pool should not be null");
return m_pCurReleasePool;
}自动释放池管理者通过pop方法,将当前自动释放池中的所有对象调用release方法进行释放,pop方法是什么时候在什么地方进行调用的呢?其实答案就在我们之前看到过的mainloop方法中:
void CCDisplayLinkDirector::mainLoop(void)
{
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
// 绘制场景
drawScene();
// 释放自动释放池
CCPoolManager::sharedPoolManager()->pop();
}
}在每一帧绘制完成之后,当前的自动释放池将会被清理,所有调用了autorelease操作的对象都会被调用release方法,减少其引用计数。如果我们创建的对象调用了autorelease,那么在稍后帧绘制之后,自动释放池被清理的时候此对象的引用计数将被减1,此对象如果没有在其他地方被Cocos2d-x学习笔记(十四)CCAutoreleasePool详解
原文地址:http://blog.csdn.net/sfh366958228/article/details/38964637