这个系列以本人游戏开发的实例来详细讲解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

好了,就这些。

一个对象添加到自动释放池后在什么时机被释放,这里不写了。后面有机会再写。