1.Ref,AutoreleasePool,PoolManager
2.源碼分析
2.1 Ref源碼分析
- void Ref::retain()
- {
- CCASSERT(_referenceCount > 0, "reference count should greater than 0");
- ++_referenceCount;
- }
- Ref* Ref::autorelease()
- {
- PoolManager::getInstance()->getCurrentPool()->addObject(this);
- return this;
- }
- void Ref::release()
- {
- CCASSERT(_referenceCount > 0, "reference count should greater than 0");
- --_referenceCount;
- if (_referenceCount == 0)
- {
- delete this;
- }
- }
其中一些Debug或者追蹤memory leak 的宏和函數我已經去掉,其實這三個函數的本質就是這麼簡單,retain和release分別增加和減少referenceCount,並且release函數在count爲0時就delete 自己。autorelease函數將Ref放入當前的AutorealsePool。
2.2AutoreleasePool 源碼分析
- void AutoreleasePool::clear()
- {
- #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
- _isClearing = true;
- #endif
- for (const auto &obj : _managedObjectArray)
- {
- obj->release();
- }
- _managedObjectArray.clear();
- #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
- _isClearing = false;
- #endif
- }
- void DisplayLinkDirector::mainLoop()
- {
- if (_purgeDirectorInNextLoop)
- {
- _purgeDirectorInNextLoop = false;
- purgeDirector();
- }
- else if (! _invalid)
- {
- drawScene();
- // release the objects
- PoolManager::getInstance()->getCurrentPool()->clear();
- }
- }
在你的App運行時,每一幀開始時都是先drawScene(),各種界面上的顯示結束後,就開始clear了。
2.3 PoolManager
AutoreleasePool *_curReleasePool;
- PoolManager* PoolManager::getInstance()
- {
- if (s_singleInstance == nullptr)
- {
- s_singleInstance = new PoolManager();
- // Add the first auto release pool
- s_singleInstance->_curReleasePool = new AutoreleasePool("cocos2d autorelease pool");
- s_singleInstance->_releasePoolStack.push_back(s_singleInstance->_curReleasePool);
- }
- return s_singleInstance;
- }
poolManager是單例模式,當第一次初始化的時候,會自動生成一個AutoreleasePool,並將其放入自己的stack中。但是,當你打開AutoreleasePool的構造函數時,發現其中已經有一個調用PoolManager::getInstance()->push(this); 通過debug跟蹤,筆者發現此時有兩個AutoRealsePool。即poolManager的stack內有兩個位置都指向同一個AutoRealsePool。感覺此處應該是一個Bug。