标签:des style color io os 使用 ar java for
【名词解释】Ref类实现了引用计数的功能,它是引擎代码中绝大多数其他类的父类,定义在CCRef.h中,实现在CCRef.cpp中。其实在CCRef.h文件中不止定义了Ref类,还定义了Clonable类、一系列的宏定义和类型定义,不过我们暂且将精力放在Ref类的解读上。Ref类使用私有成员变量_referenceCount保存计数值,并通过retain,release和autorelease函数实现增减计数值。
<span style="font-family:Microsoft YaHei;font-size:18px;">class CC_DLL Ref { public: /** * Retains the ownership. * * This increases the Ref's reference count. * * @see release, autorelease * @js NA */ void retain(); /** * Releases the ownership immediately. * * This decrements the Ref's reference count. * * If the reference count reaches 0 after the descrement, this Ref is * destructed. * * @see retain, autorelease * @js NA */ void release(); /** * Releases the ownership sometime soon automatically. * * This descrements the Ref's reference count at the end of current * autorelease pool block. * * If the reference count reaches 0 after the descrement, this Ref is * destructed. * * @returns The Ref itself. * * @see AutoreleasePool, retain, release * @js NA * @lua NA */ Ref* autorelease(); /** * Returns the Ref's current reference count. * * @returns The Ref's reference count. * @js NA */ unsigned int getReferenceCount() const; protected: /** * Constructor * * The Ref's reference count is 1 after construction. * @js NA */ Ref(); public: /** * @js NA * @lua NA */ virtual ~Ref(); protected: /// count of references unsigned int _referenceCount; friend class AutoreleasePool; };</span>Ref将构造函数声明为保护类型,防止直接生成Ref对象,在构造函数的成员初始化列表中将引用计数值_referenceCount初始化为1。retain函数将_referenceCount加1,release函数则减1,autorelease函数则将对象托管给AutoreleasePool对象进行管理,具体实现代码如下:
<span style="font-family:Microsoft YaHei;font-size:18px;">NS_CC_BEGIN Ref::Ref() : _referenceCount(1) // when the Ref is created, the reference count of it is 1 { } Ref::~Ref() { } void Ref::retain() { CCASSERT(_referenceCount > 0, "reference count should greater than 0"); ++_referenceCount; } void Ref::release() { CCASSERT(_referenceCount > 0, "reference count should greater than 0"); --_referenceCount; if (_referenceCount == 0) { delete this; } } Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addObject(this); return this; } unsigned int Ref::getReferenceCount() const { return _referenceCount; } NS_CC_END</span>【Clonable类的定义】
<span style="font-family:Microsoft YaHei;font-size:18px;">/** Interface that defines how to clone an Ref */ class CC_DLL Clonable { public: /** returns a copy of the Ref */ virtual Clonable* clone() const = 0; /** * @js NA * @lua NA */ virtual ~Clonable() {}; /** returns a copy of the Ref. * @deprecated Use clone() instead */ CC_DEPRECATED_ATTRIBUTE Ref* copy() const { // use "clone" instead CC_ASSERT(false); return nullptr; } };</span>【回调函数的定义】
<span style="font-family:Microsoft YaHei;font-size:18px;">typedef void (Ref::*SEL_CallFunc)(); typedef void (Ref::*SEL_CallFuncN)(Node*); typedef void (Ref::*SEL_CallFuncND)(Node*, void*); typedef void (Ref::*SEL_CallFuncO)(Ref*); typedef void (Ref::*SEL_MenuHandler)(Ref*); typedef void (Ref::*SEL_SCHEDULE)(float); #define callfunc_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR) #define callfuncN_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR) #define callfuncND_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR) #define callfuncO_selector(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR) #define menu_selector(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR) #define schedule_selector(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)</span>上面回调函数的定义分为两步:类型定义和宏定义。我们以SEL_CallFuncO为例进行说明,首先通过typedef类型定义了一个成员函数指针SEL_CallFuncO,SEL_CallFuncO是Ref类的成员,同时接收Ref类型的指针形参:
<span style="font-family:Microsoft YaHei;font-size:18px;">#define CC_USE_MEM_LEAK_DETECTION 0</span>
作为开关的。内存泄漏检测代码主要包括Ref类静态成员函数:
<span style="font-family:Microsoft YaHei;font-size:18px;">class CC_DLL Ref { // Memory leak diagnostic data (only included when CC_USE_MEM_LEAK_DETECTION is defined and its value isn't zero) #if CC_USE_MEM_LEAK_DETECTION public: static void printLeaks(); #endif };</span>
定义在CCRef.cpp文件内的静态函数(静态函数与普通函数不同之处在于,它只在声明它的文件中可见,其他文件不可见,同时,其他文件中可以定义相同名字的函数,不会发生冲突)
#if CC_USE_MEM_LEAK_DETECTION static void trackRef(Ref* ref); static void untrackRef(Ref* ref); #endiftrackRef函数在Ref类对象创建的时候调用,untrackRef在Ref类对象销毁的时候调用,Ref对象实例保存在静态链表__refAllocationList中,实现代码如下所示:
#if CC_USE_MEM_LEAK_DETECTION static std::list<Ref*> __refAllocationList; void Ref::printLeaks() { // Dump Ref object memory leaks if (__refAllocationList.empty()) { log("[memory] All Ref objects successfully cleaned up (no leaks detected).\n"); } else { log("[memory] WARNING: %d Ref objects still active in memory.\n", (int)__refAllocationList.size()); for (const auto& ref : __refAllocationList) { CC_ASSERT(ref); const char* type = typeid(*ref).name(); log("[memory] LEAK: Ref object '%s' still active with reference count %d.\n", (type ? type : ""), ref->getReferenceCount()); } } } static void trackRef(Ref* ref) { CCASSERT(ref, "Invalid parameter, ref should not be null!"); // Create memory allocation record. __refAllocationList.push_back(ref); } static void untrackRef(Ref* ref) { auto iter = std::find(__refAllocationList.begin(), __refAllocationList.end(), ref); if (iter == __refAllocationList.end()) { log("[memory] CORRUPTION: Attempting to free (%s) with invalid ref tracking record.\n", typeid(*ref).name()); return; } __refAllocationList.erase(iter); } #endif // #if CC_USE_MEM_LEAK_DETECTION
[当我在研究Cocos-2dx的源码时,我在想什么]-Ref类,一切的起源
标签:des style color io os 使用 ar java for
原文地址:http://blog.csdn.net/asce1885/article/details/39958963