COCOCOCOS学習ノート--メモリ管理(二)-PoolManager類とAutonese Pool類の解説


前のブログではCocod 2 dxメモリ管理(一)--参照カウントとRefの説明
(http://blog.csdn.net/gzy252050968/article/details/50459012)
Cocos 2 d-xでは参照カウントを使ってメモリ管理を行い、Refクラスでは retain()、release()、autrelease()方法は、カウントアップ、カウントダウン、および1つのオブジェクトをAutoreelease Poolに渡して管理し、Autoreleaseオブジェクトからrelease関数の呼び出しを行いますが、メモリ管理クラスPool Managerおよび自動放出池Autorelearse Pool類は、具体的にどのように管理していますか?
まずCCAutonersePool類を見に行きます.主に以下の方法があります.
AutoreleasePool();//  
AutoreleasePool(const std::string &name);//       
~AutoreleasePool();//  
void addObject(Ref *object);// Ref        
void clear();//           
bool contains(Ref* object) const;//           Object  
void dump();//          
一つずつ見に来ました.
コンストラクタ:
AutoreleasePool::AutoreleasePool()
    : _name("")//     ””
    #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
        , _isClearing(false)//  sClearing false
    #endif
    {	//    ,    ref vector size  150
        _managedObjectArray.reserve(150);
        // AutoreleasePool         vector 
        PoolManager::getInstance()->push(this);
    }
コンストラクションでは、各自動放出池AutonersePoolのオブジェクトに、Objを管理するキューmanage dObject Arayをプールに保存するためのObjがあります.そして、すべてのAutorsePoolオブジェクトは、PoolManagerの単一のオブジェクトの山の中に置かれています.この後、PoolManager類のコードを見れば分かります.
構文関数:
AutoreleasePool::~AutoreleasePool()
{
    CCLOGINFO("deallocing AutoreleasePool: %p", this);
    //  
    clear();
    //  
    PoolManager::getInstance()->pop();
}
注意Autonerse Pool解析関数は、まず自動放出プールのすべてのobjオブジェクトをクリアしてから、自分をPoolManagerの単一の例のヒープからイジェクトします.
Objectをmanage dObject Aray自動放出池に追加します.
void AutoreleasePool::addObject(Ref* object)
{
    _managedObjectArray.push_back(object);
}
見ましたよね.各AutoeleasPoolオブジェクトは一つの列を維持するためにマンチェスターObject ArayにたくさんのObjを入れることができます.
clear()の方法は、Autoelease Poolオブジェクトが自分のメンテナンスしているキューmanage dObject Arayの各objをrelease()に実行することである.
void AutoreleasePool::clear()
{
    #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
        _isClearing = true;//          
    #endif
    std::vector<Ref*> releasings;
    releasings.swap(_managedObjectArray);
    //       managedObjectArray       Ref
    for (const auto &obj : releasings)
    {
        //  obj release(), obj     -1(         0   )
        obj->release();
    }
    #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
        _isClearing = false;//          
    #endif
}
残りの二つの方法は多く言わないで、注釈を見ればいいです.
contains()方法は自動釈放池にあるRefが含まれているかどうかを判断する.
bool AutoreleasePool::contains(Ref* object) const
{
    //       managedObjectArray
    for (const auto& obj : _managedObjectArray)
    {
        //    
        if (obj == object)
            //return true       managedObjectArray     
            return true;
     }
    return false;
}
自動リリースプールの各ノード情報を印刷します.
void AutoreleasePool::dump()
{
    //       managedObjectArray size,    
    CCLOG("autorelease pool: %s, number of managed object %d
", _name.c_str(), static_cast<int>(_managedObjectArray.size())); CCLOG("%20s%20s%20s", "Object pointer", "Object id", "reference count"); for (const auto &obj : _managedObjectArray) { CC_UNUSED_PARAM(obj); // CCLOG("%20p%20u
", obj, obj->getReferenceCount()); } }
はい、次はPoolManager類を見ます.このクラスはAutoelease Poolを管理します.
まず最初の書類を見てください.この種類には何がありますか?
class CC_DLL PoolManager
{
public:
 
    CC_DEPRECATED_ATTRIBUTE static PoolManager* sharedPoolManager() { return getInstance(); }
    static PoolManager* getInstance();//  PoolManager    ,          
    CC_DEPRECATED_ATTRIBUTE static void purgePoolManager() { destroyInstance(); }
    static void destroyInstance();//  PoolManager       
    AutoreleasePool *getCurrentPool() const;//     autoreleasepool   
    bool isObjectInPools(Ref* obj) const;//   obj   autoreleasepool 
    friend class AutoreleasePool;// AutoreleasePool      
 
    
private:
    PoolManager();
    ~PoolManager();
    void push(AutoreleasePool *pool); //  
    void pop();//  
    static PoolManager* s_singleInstance; //poolmanager   ,            
    std::vector<AutoreleasePool*> _releasePoolStack;//   !   poolmanager      ,      AutoreleasePool  
};
それでは、PoolManager類以上のこれらの方法の具体的な実現を見に行きます.
まず、PoolManagerの単一例の対象single Instanceを設定しました. nullptrのため:
PoolManager* PoolManager::s_singleInstance = nullptr;
PoolManagerの単一例の対象を得る方法:
PoolManager* PoolManager::getInstance()
{
    //      singleInstance 
    if (s_singleInstance == nullptr)
    {
        //  singleInstance  nullptr,new  PoolManager  
        s_singleInstance = new (std::nothrow) PoolManager();
        //new  AutoreleasePool     "cocos2d autorelease pool"
        new AutoreleasePool("cocos2d autorelease pool");
    }
    return s_singleInstance;
}
この方法はPoolManagerの単一の例の対象を得ることができます.もしnew一つがなかったら、何が単例の対象ですか?このようなプロジェクト全体にはこのような例の対象しかないです.これはデザインモードの中の一例モデルの餓漢式です.以前のブログでも紹介しました.興味がある人は見てもいいです.
この方法にはコードがあります.    
new AutoreleasePool("cocos2d autorelease pool");
このコードは非常に重要です.これはPoolManager類です. のget Instance()方法でAutonersePoolを作成しました.つまり、get Instance()を通じてPool Managerオブジェクトを獲得した時には、AutonersePoolオブジェクトが既にバインドされています.このAutorsePoolの名前は「cocococococos 2 d」です. autrelease pool「これは私達のシステムで初めて作成したAutonersePoolです.エンジンの運行メカニズムはCocosプロジェクトが起動した時にPoolManagerを呼び出すからです. autrelease pool"の自動放出池のオブジェクトは、レンダリングされたノードのほとんどを保存するために使用され、create()を介して作成されたオブジェクトであり、Cococococos 2 d-xの中で最も使用頻度が高いAutoelease Poolである.
PoolManagerの単一例のオブジェクトを削除します.
void PoolManager::destroyInstance()
{
    delete s_singleInstance;
    s_singleInstance = nullptr;
}
コンストラクタ:
PoolManager::PoolManager()
{
    //  releasePoolStack   size
    //         AutoreleasePool  
    _releasePoolStack.reserve(10);
}
構文関数:
PoolManager::~PoolManager()
{
    CCLOGINFO("deallocing PoolManager: %p", this);
    
    while (!_releasePoolStack.empty())
   {
        //      AutoreleasePool  
        AutoreleasePool* pool = _releasePoolStack.back();
        //  
        delete pool;
    }
}
PoolManagerのコンフィギュレーション関数は、そのメンテナンスのためのヒープrelease PoolStarkの末尾から始まり、AutorsePoolオブジェクトを一つずつ削除します.
現在のAutonersePoolオブジェクトを取得しました.
AutoreleasePool* PoolManager::getCurrentPool() const
{
    //         PoolManager  AutoreleasePool  
    return _releasePoolStack.back();
}
あるobjがそのヒープの中に保存されているAutorsePoolにあるかどうかを判断する:
bool PoolManager::isObjectInPools(Ref* obj) const
{
    //     AutoreleasePool
    for (const auto& pool : _releasePoolStack)
   {
        //  pool   obj,  true
        if (pool->contains(obj))
            return true;
    }
    return false;
}
PoolManagerにpoolを追加します.
//        
void PoolManager::push(AutoreleasePool *pool)
{
    _releasePoolStack.push_back(pool);
}
PoolManager山の末尾のpoolを削除します.
void PoolManager::pop()
{
    CC_ASSERT(!_releasePoolStack.empty());
    _releasePoolStack.pop_back();
}
はい、これでPoolManager類とAutorsePool類の説明は終わりました.
最後にまとめます.
1.各自動釈放池AutorsePool類のオブジェクトの中では、いくつかのRefオブジェクトobjを保存するために、1つのキューmanage dObject Arayが維持されている.
2.Autonese Pool類は、addObject()、clear()、contains()、dump()などの方法を提供し、その池のObjを管理する.
3.Autoelease Pool:clear()方法でRef:release()方法を呼び出しました.
4.PoolManager類の対象は一例の対象single Instanceです. ,プロジェクトの中で一つだけです.
5.PoolManager類は1つのヒープrelease PoolStockを維持していて、工事の中ですべてのAutorsePoolオブジェクトを保管するために使用します.
6.名前は「cocococos 2 d」です autrelease pool"の自動放出池のオブジェクト保存プロジェクトの中のほとんどのレンダリングノードと私達がcreateを通じて作成したオブジェクトは、このAutoelease Poolオブジェクトはプロジェクトが起動した直後に生成されます.
7.PoolManager類は、get Instance()、destroyInstance()、get CurrenntPool()、isObject InPools()、push()、pop()などの方法を提供して、すべての自動放出池AutorselePoolオブジェクトを管理します.
 
以上です.