cocos2dx源码简读--Ref



#ifndef __BASE_CCREF_H__

#define __BASE_CCREF_H__


#include "platform/CCPlatformMacros.h"

#include "base/ccConfig.h”//这里是关于使用什么东西的,想缩包就改宏


NS_CC_BEGIN //就是namespace cocos2d {


class Ref;


class CC_DLL Clonable//一个接口  规定了如何克隆

{

public:

    

    virtual Clonable* clone() const = 0;

   

    virtual ~Clonable() {};


   

    CC_DEPRECATED_ATTRIBUTE Ref* copy() const

    {


        CC_ASSERT(false);

        return nullptr;

    }

};


class CC_DLL Ref  //cocos2dx Node的老祖宗

{

public:

    

    void retain(); //保留   引用加一


   

    void release();//释放  引用减一


    

    Ref* autorelease();// 自动释放   就是把自己添加到引用释放池中


   

    unsigned int getReferenceCount() const;//返回引用计数


protected:

    

    Ref();


public:

    

    virtual ~Ref();


protected:

    

    unsigned int _referenceCount;//引用计数


    friend class AutoreleasePool;//把引用释放池作为友元类  


#if CC_ENABLE_SCRIPT_BINDING   //脚本相关   cocos2dx 可以使用lua javascript语言 

public:

    /// object id, ScriptSupport need public _ID

    unsigned int        _ID;

    /// Lua reference id

    int                 _luaID;

    /// scriptObject, support for swift

    void* _scriptObject;

#endif


    // Memory leak diagnostic data (only included when CC_REF_LEAK_DETECTION is defined and its value isn't zero)

#if CC_REF_LEAK_DETECTION

public:

    static void printLeaks();

#endif

};


class Node;


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 CC_CALLFUNC_SELECTOR(_SELECTOR)  static_cast<cocos2d::SEL_CallFunc>(&_SELECTOR) //#define ()中的是参数

#define CC_CALLFUNCN_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_CallFuncN>(&_SELECTOR)

#define CC_CALLFUNCND_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_CallFuncND>(&_SELECTOR)

#define CC_CALLFUNCO_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_CallFuncO>(&_SELECTOR)

#define CC_MENU_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_MenuHandler>(&_SELECTOR)

#define CC_SCHEDULE_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)


// Deprecated

#define callfunc_selector(_SELECTOR) CC_CALLFUNC_SELECTOR(_SELECTOR)

#define callfuncN_selector(_SELECTOR) CC_CALLFUNCN_SELECTOR(_SELECTOR)

#define callfuncND_selector(_SELECTOR) CC_CALLFUNCND_SELECTOR(_SELECTOR)

#define callfuncO_selector(_SELECTOR) CC_CALLFUNCO_SELECTOR(_SELECTOR)

#define menu_selector(_SELECTOR) CC_MENU_SELECTOR(_SELECTOR)

#define schedule_selector(_SELECTOR) CC_SCHEDULE_SELECTOR(_SELECTOR)




NS_CC_END // }


#endif // __BASE_CCREF_H__



-----------h和cpp的分割线----------------





#include "base/CCRef.h"

#include "base/CCAutoreleasePool.h"

#include "base/ccMacros.h"

#include "base/CCScriptSupport.h"


#if CC_REF_LEAK_DETECTION

#include <algorithm>    // std::find

#endif


NS_CC_BEGIN


#if CC_REF_LEAK_DETECTION

static void trackRef(Ref* ref);

static void untrackRef(Ref* ref);

#endif


Ref::Ref()

: _referenceCount(1) // 等同与_referenceCount=1   _referenceCount(1)这么写对于class来说就是调用构造函数进行初始化,这种方式可以初始化const

{

#if CC_ENABLE_SCRIPT_BINDING  // 脚本相关

    static unsigned int uObjectCount = 0;

    _luaID = 0;

    _ID = ++uObjectCount;

    _scriptObject = nullptr;

#endif

    

#if CC_REF_LEAK_DETECTION

    trackRef(this);

#endif

}


Ref::~Ref()

{

#if CC_ENABLE_SCRIPT_BINDING  // 脚本相关

    // if the object is referenced by Lua engine, remove it

    if (_luaID)

    {

        ScriptEngineManager::getInstance()->getScriptEngine()->removeScriptObjectByObject(this);

    }

    else

    {

        ScriptEngineProtocol* pEngine = ScriptEngineManager::getInstance()->getScriptEngine();

        if (pEngine != nullptr && pEngine->getScriptType() == kScriptTypeJavascript)

        {

            pEngine->removeScriptObjectByObject(this);

        }

    }

#endif



#if CC_REF_LEAK_DETECTION

    if (_referenceCount != 0)

        untrackRef(this);

#endif

}


void Ref::retain()

{

    CCASSERT(_referenceCount > 0, "reference count should be greater than 0”);//断言必须_referenceCount > 0

    ++_referenceCount;  

}


void Ref::release()

{

    CCASSERT(_referenceCount > 0, "reference count should be 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))//debug模式下如果引用计数已经为0并且这个对象还在自动释放池里面,报一个警告

        {

          

            CCASSERT(false, "The reference shouldn't be 0 because it is still in autorelease pool.");

        }

#endif


#if CC_REF_LEAK_DETECTION

        untrackRef(this);

#endif

        delete this;

    }

}


Ref* Ref::autorelease()

{

    PoolManager::getInstance()->getCurrentPool()->addObject(this);

    return this;

}


unsigned int Ref::getReferenceCount() const

{

    return _referenceCount;

}


#if CC_REF_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_REF_LEAK_DETECTION



NS_CC_END



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值