一、引用计数
基类Ref的作用就是通过引用计数来管理对象的生命周期,引用计数规则:
- 引用计数
- _referenceCount,初始为1。
- retain()
- _referenceCount加1。
- release()
- _referenceCount减1,如果此时为0了,删除对象。
cocos几乎所有对象都继承自Ref。
下面是Ref中引用计数相关的源码。
class CC_DLL Ref
{
public:
void retain(); // _referenceCount + 1
void release(); // _referenceCount - 1
Ref* autorelease(); // 加入当前的autoReleasePool
unsigned int getReferenceCount() const; // 当前的引用计数
protected:
Ref(); // _referenceCount初始为1
protected:
unsigned int _referenceCount; // 当前这个对象的引用计数
......
};
Ref::Ref()
: _referenceCount(1){
}
void Ref::retain(){
++_referenceCount;
}
void Ref::release(){
--_referenceCount;
if (_referenceCount == 0)
{
delete this;
}
}
unsigned int Ref::getReferenceCount() const{
return _referenceCount;
}
Ref* Ref::autorelease() //加入到当前的Pool中,见下面
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
二、自动化管理
我们已经能够管理cocos对象的生命周期,但是很麻烦,必须手动retain、release,我们可以借助渲染循环作为作为“驱动力”,来实现自动化。
cocos用一个AutoReleasePool来管理需要auto relase的Ref对象,用一个栈结构来保存pool,在帧结尾处,当前pool(栈顶pool)的所有对象release一次。
void Director::mainLoop()
{
......;
drawScene();
......
PoolManager::getInstance()->getCurrentPool()->clear(); // release the objects
......
}
使用方法示例如下:
void fuck()
{
// 在构造时候,poolManager将pool压栈 即成为current pool
// pool在析构时,pool中所有Ref对象都将release一次,并弹栈
AutoReleasePool pool;
Node *pNode1 = Node::create(); // 加入current pool
Node *pNode2 = Node::create(); // 加入current pool
Ref *pRef = new Ref();
pRef->autorelease(); // 加入current pool
Director::getInstnace()->getRunningScene()->addChild(pNode1);
}
// 函数结束,触发pool的析构,上面所有Ref对象都release一次,
// release之后,引用计数情况如下:
// pNode1->release之后,引用计数=1,当runningScene->removeChild(pNode1)时,pNode1将被delete
// pNode2->release之后,引用计数=0,立即被delete
// pRef->release之后,引用计数=0,立即被delete
AutoreleasePool
自动回收池,存储要进行AutoRelease的Ref对象。
std::vector<Ref*> _managedObjectArray; // 存储要autoRelease的对象
AutoreleasePool::AutoreleasePool(){
// 预计管理的对象数量不会超过150个。
_managedObjectArray.reserve(150);
PoolManager::getInstance()->push(this); //设置为当前的AutoreleasePool
}
AutoreleasePool::~AutoreleasePool(){ //清空池,所有对象release
clear();
PoolManager::getInstance()->pop(); //当前AutoreleasePool改为上一个
}
void AutoreleasePool::addObject(Ref* object){ //对象加入AutoreleasePool
_managedObjectArray.push_back(object);
}
void AutoreleasePool::clear(){ //清空池,所有对象release
std::vector<Ref*> releasings;
releasings.swap(_managedObjectArray);
for (const auto &obj : releasings){
obj->release();
}
}
PoolManager
通过一个栈来管理AutoreleasePool,需要自动回收的对象都将被添加到栈顶的Pool中,即当前的Pool。
栈底初始有一个常驻的Pool。
部分源码如下:
// 栈结构,保存auto release pool,栈顶pool为当前pool
std::vector<AutoreleasePool*> _releasePoolStack;
PoolManager* PoolManager::getInstance(){
if (s_singleInstance == nullptr){
s_singleInstance = new (std::nothrow) PoolManager();
new AutoreleasePool("cocos2d autorelease pool"); // 栈底初始就有一个Pool
}
return s_singleInstance;
}
PoolManager::PoolManager(){
_releasePoolStack.reserve(10); // Pool最好限制在10个以内。
}
AutoreleasePool* PoolManager::getCurrentPool() const { // 栈顶Pool
return _releasePoolStack.back();
}
void PoolManager::push(AutoreleasePool *pool){
_releasePoolStack.push_back(pool);
}
void PoolManager::pop(){
_releasePoolStack.pop_back();
}