class
CC_DLL
Ref
{
public
:
/**
引用计数+1
*/
void
retain();
{
CCASSERT
(_referenceCount > 0,
"reference count should greater than 0"
);
++_referenceCount;
}
/**
引用计数-1
*/
void
release();
{
CCASSERT
(_referenceCount > 0,
"reference count should greater than 0"
);
--_referenceCount;
if
(_referenceCount == 0)
{
#if
defined
(
COCOS2D_DEBUG
) && (
COCOS2D_DEBUG
> 0)
auto
poolManager =
PoolManager
::getInstance();
if
(!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(
this
))
{
// 错误实例1:
// auto obj = Node::create();
// obj->autorelease();
//create函数里面封装了
autorelease
// 错误实例2:
// auto obj = Node::create();
// obj->release(); // Wrong: obj is an autorelease Ref,it will be released when clearing current pool.
CCASSERT
(
false
,
"The reference shouldn't be 0 because it is still in autorelease pool."
);
}
#endif
#if
CC_USE_MEM_LEAK_DETECTION
untrackRef(
this
);
#endif
delete
this
;
}
/**
*/
Ref
* autorelease();
{
PoolManager
::getInstance()->getCurrentPool()->addObject(
this
);
return
this
;
}
/**
* 返回引用数量
*/
unsigned
int
getReferenceCount()
const
;
protected
:
/**
* 在构造了之后引用计数是1!!!!!
*/
Ref()
: _referenceCount(1)
// when the Ref is created,the reference count of it is 1
{
#if
CC_ENABLE_SCRIPT_BINDING
static
unsigned
int
uObjectCount = 0;
_luaID = 0;
_ID = ++uObjectCount;
#endif
#if
CC_USE_MEM_LEAK_DETECTION
trackRef(
this
);
#endif
}
public
:
virtual
~Ref();
protected
:
/// count of references
unsigned
int
_referenceCount;
friend
class
AutoreleasePool
;
#if
CC_ENABLE_SCRIPT_BINDING
public
:
/// object id,ScriptSupport need public _ID
unsigned
int
_ID;
/// Lua reference id
int
_luaID;
#endif
#if
CC_USE_MEM_LEAK_DETECTION
public
:
static
void
printLeaks();
#endif
};
PoolManager类的解析:
class
CC_DLL
PoolManager
{
public
:
//这个是表示这个接口以后要丢弃
CC_DEPRECATED_ATTRIBUTE
static
PoolManager
* sharedPoolManager() {
return
getInstance(); }
static
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;
}
CC_DEPRECATED_ATTRIBUTE
static
void
purgePoolManager() { destroyInstance(); }
static
void
destroyInstance();
/**
* 获得现在的释放池,引擎自己创建了一个autoreleasePool
* 你可以创建自己的释放池 会放进自动释放池的盏变量里面
*/
AutoreleasePool
*getCurrentPool()
const
;
{
return
_curReleasePool;
}
bool
isObjectInPools(
Ref
* obj)
const
;
friend
class
AutoreleasePool
;
private
:
PoolManager();
~PoolManager();
void
push(
AutoreleasePool
*pool);
{
_releasePoolStack.push_back(
pool
);
_curReleasePool =
pool
;
}
void
pop();
{
// 如果是弹出第一个
CC_ASSERT
(_releasePoolStack.size() >= 1);
_releasePoolStack.pop_back();
// 应该更新
_curReleasePool
if
(_releasePoolStack.size() > 1)
{
_curReleasePool = _releasePoolStack.back();
}
}
static
PoolManager
* s_singleInstance;//单例模式
};
AutoreleasePool
class
CC_DLL
AutoreleasePool
{
public
:
/**
* 创建的时候就自动push进PoolManager里面
*/
AutoreleasePool();
{
_managedObjectArray.reserve(150);//vector扩大容量
PoolManager
::getInstance()->push(
this
);
}
/**
* 用引用来创建 是为了调试
*/
AutoreleasePool(
const
std::
string
&name);
{
_managedObjectArray.reserve(150);
PoolManager
::getInstance()->push(
this
);
}
//
枚举每一个加进对象池的obj去调用release 并且清空
~AutoreleasePool();
{
CCLOGINFO
(
"deallocing AutoreleasePool: %p"
,
this
);
clear();//
PoolManager
::getInstance()->pop();
}
/**
* 添加对象到对象池中
* 对象池销毁的时候会调用
*/
void
addObject(
Ref
*object);
{
_managedObjectArray.push_back(
object
);
}
/**
*/
void
clear();
{
#if
defined
(
COCOS2D_DEBUG
) && (
COCOS2D_DEBUG
> 0)
_isClearing =
true
;
#endif
for
(
const
auto
&obj : _managedObjectArray)
{
//枚举每一个加进对象池的obj去调用release
obj->release();
}
//把vector清空
_managedObjectArray.clear();
#if
defined
(
COCOS2D_DEBUG
) && (
COCOS2D_DEBUG
> 0)
_isClearing =
false
;
#endif
}
#if
defined
(
COCOS2D_DEBUG
) && (
COCOS2D_DEBUG
> 0)
/**
* Whether the pool is doing `clear` operation.
*/
bool
isClearing()
const
{
return
_isClearing; };
#endif
/**
* 检查是否包含
* 枚举一遍这个vector
*/
bool
contains(
Ref
* object)
const
;
{
for
(
const
auto
& obj : _managedObjectArray)
{
if
(obj ==
object
)
return
true
;
}
return
false
;
}
/**
* 用来调试
*
*/
void
dump();
{
CCLOG
(
"autorelease pool: %s,number of managed object %d\n"
,_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\n"
,obj,obj->getReferenceCount());
}
}
private
:
/**
* The underlying array of object managed by the pool.
*
* Although Array retains the object once when an object is added,proper
* Ref::release() is called outside the array to make sure that the pool
* does not affect the managed object's reference count. So an object can
* be destructed properly by calling Ref::release() even if the object
* is in the pool.
*/
std::
vector
<
Ref
*> _managedObjectArray;
std::
string
_name;
#if
defined
(
COCOS2D_DEBUG
) && (
COCOS2D_DEBUG
> 0)
/**
* The flag for checking whether the pool is doing `clear` operation.
*/
bool
_isClearing;
#endif
};
下面这张图是网上找的类图继承图: