cocos2dx 源码分析之 CCPoolManager

来源:互联网 发布:编程软件图标 编辑:程序博客网 时间:2024/05/16 17:59

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_BEGINstatic 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
0 0
原创粉丝点击