cocos2dx 源码分析之 CCPoolManager

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值