mirror of https://github.com/axmolengine/axmol.git
Merge the alternate RefPtr<T> implementation
Merge in the version at: https://github.com/DarraghCoy/cocos2d-x/blob/add_refptr_class_alt_impl/cocos/base/CCRefPtr.h This version sacrifices the ability to use forward references in some places in return for added type safety and ensures we can never assign a non cocos2d::Ref derived object to the pointer.
This commit is contained in:
parent
586383a05e
commit
f147ef723a
|
@ -1 +1 @@
|
||||||
f722a4d89963f2d2a58b754e12d1baa2bf0c5ece
|
a6890abb8134492d61129c585fbd28941e825a6f
|
|
@ -1,51 +0,0 @@
|
||||||
/****************************************************************************
|
|
||||||
Copyright (c) 2014 PlayFirst Inc.
|
|
||||||
Copyright (c) 2014 Chukong Technologies Inc.
|
|
||||||
|
|
||||||
http://www.cocos2d-x.org
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "CCRefPtr.h"
|
|
||||||
#include "CCRef.h"
|
|
||||||
|
|
||||||
NS_CC_BEGIN
|
|
||||||
|
|
||||||
void RefPtrSupportFunctions::safeRetainRef(const void * refPtr)
|
|
||||||
{
|
|
||||||
if (refPtr)
|
|
||||||
{
|
|
||||||
Ref * refPtrCast = reinterpret_cast<Ref*>(const_cast<void*>(refPtr));
|
|
||||||
CC_ASSERT(dynamic_cast<Ref*>(refPtrCast)); // Check for invalid type pointed to in RefPtr. Object pointed to must be a cocos2d::Ref!
|
|
||||||
refPtrCast->retain();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RefPtrSupportFunctions::safeReleaseRef(const void * refPtr)
|
|
||||||
{
|
|
||||||
if (refPtr)
|
|
||||||
{
|
|
||||||
Ref * refPtrCast = reinterpret_cast<Ref*>(const_cast<void*>(refPtr));
|
|
||||||
CC_ASSERT(dynamic_cast<Ref*>(refPtrCast)); // Check for invalid type pointed to in RefPtr. Object pointed to must be a cocos2d::Ref!
|
|
||||||
refPtrCast->release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_CC_END
|
|
|
@ -26,23 +26,48 @@
|
||||||
#ifndef __CC_REF_PTR_H__
|
#ifndef __CC_REF_PTR_H__
|
||||||
#define __CC_REF_PTR_H__
|
#define __CC_REF_PTR_H__
|
||||||
|
|
||||||
#include "CCPlatformMacros.h"
|
#include "CCRef.h"
|
||||||
#include "ccConfig.h"
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
class Ref;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility/support functions for RefPtr.
|
* Utility/support macros. Defined to enable RefPtr<T> to contain types like 'const T' because we do not
|
||||||
|
* regard retain()/release() as affecting mutability of state.
|
||||||
*/
|
*/
|
||||||
namespace RefPtrSupportFunctions
|
#define CC_REF_PTR_SAFE_RETAIN(ptr)\
|
||||||
{
|
\
|
||||||
void safeRetainRef(const void * refPtr);
|
do\
|
||||||
|
{\
|
||||||
void safeReleaseRef(const void * refPtr);
|
if (ptr)\
|
||||||
}
|
{\
|
||||||
|
const_cast<Ref*>(static_cast<const Ref*>(ptr))->retain();\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define CC_REF_PTR_SAFE_RELEASE(ptr)\
|
||||||
|
\
|
||||||
|
do\
|
||||||
|
{\
|
||||||
|
if (ptr)\
|
||||||
|
{\
|
||||||
|
const_cast<Ref*>(static_cast<const Ref*>(ptr))->release();\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define CC_REF_PTR_SAFE_RELEASE_NULL(ptr)\
|
||||||
|
\
|
||||||
|
do\
|
||||||
|
{\
|
||||||
|
if (ptr)\
|
||||||
|
{\
|
||||||
|
const_cast<Ref*>(static_cast<const Ref*>(ptr))->release();\
|
||||||
|
ptr = nullptr;\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
} while (0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class which maintains a strong reference to a cocos2dx cocos2d::Ref* type object.
|
* Wrapper class which maintains a strong reference to a cocos2dx cocos2d::Ref* type object.
|
||||||
|
@ -57,67 +82,89 @@ namespace RefPtrSupportFunctions
|
||||||
template <typename T> class RefPtr
|
template <typename T> class RefPtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
RefPtr()
|
||||||
|
: _ptr(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr() = default;
|
|
||||||
|
|
||||||
inline RefPtr(T * ptr)
|
inline RefPtr(T * ptr)
|
||||||
:
|
:
|
||||||
_ptr(ptr)
|
_ptr(const_cast<typename std::remove_const<T>::type*>(ptr)) // Const cast allows RefPtr<T> to reference objects marked const too.
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeRetainRef(_ptr);
|
CC_REF_PTR_SAFE_RETAIN(_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline RefPtr(std::nullptr_t ptr)
|
||||||
|
:
|
||||||
|
_ptr(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RefPtr(const RefPtr<T> & other)
|
inline RefPtr(const RefPtr<T> & other)
|
||||||
:
|
:
|
||||||
_ptr(other._ptr)
|
_ptr(other._ptr)
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeRetainRef(_ptr);
|
CC_REF_PTR_SAFE_RETAIN(_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~RefPtr()
|
inline ~RefPtr()
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeReleaseRef(_ptr);
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
||||||
_ptr = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RefPtr & operator = (const RefPtr<T> & other)
|
inline RefPtr & operator = (const RefPtr<T> & other)
|
||||||
{
|
{
|
||||||
if (other._ptr != _ptr)
|
if (other._ptr != _ptr)
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeRetainRef(other._ptr);
|
CC_REF_PTR_SAFE_RETAIN(other._ptr);
|
||||||
RefPtrSupportFunctions::safeReleaseRef(_ptr);
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
||||||
_ptr = other._ptr;
|
_ptr = other._ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline RefPtr & operator = (std::nullptr_t other)
|
||||||
|
{
|
||||||
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline RefPtr & operator = (T * other)
|
inline RefPtr & operator = (T * other)
|
||||||
{
|
{
|
||||||
if (other != _ptr)
|
if (other != _ptr)
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeRetainRef(other);
|
CC_REF_PTR_SAFE_RETAIN(other);
|
||||||
RefPtrSupportFunctions::safeReleaseRef(_ptr);
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
||||||
_ptr = other;
|
_ptr = const_cast<typename std::remove_const<T>::type*>(other); // Const cast allows RefPtr<T> to reference objects marked const too.
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator T * () const { return _ptr; }
|
// Note: using reinterpret_cast<> instead of static_cast<> here because it doesn't require type info.
|
||||||
|
// Since we verify the correct type cast at compile time on construction/assign we don't need to know the type info
|
||||||
|
// here. Not needing the type info here enables us to use these operations in inline functions in header files when
|
||||||
|
// the type pointed to by this class is only forward referenced.
|
||||||
|
|
||||||
|
inline operator T * () const { return reinterpret_cast<T*>(_ptr); }
|
||||||
|
|
||||||
inline T & operator * () const
|
inline T & operator * () const
|
||||||
{
|
{
|
||||||
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
||||||
return *_ptr;
|
return reinterpret_cast<T&>(*_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T * operator->() const
|
inline T * operator->() const
|
||||||
{
|
{
|
||||||
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
||||||
return _ptr;
|
return reinterpret_cast<T*>(_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline T * get() const { return reinterpret_cast<T*>(_ptr); }
|
||||||
|
|
||||||
|
|
||||||
inline bool operator == (const RefPtr<T> & other) const { return _ptr == other._ptr; }
|
inline bool operator == (const RefPtr<T> & other) const { return _ptr == other._ptr; }
|
||||||
|
|
||||||
inline bool operator == (const T * other) const { return _ptr == other; }
|
inline bool operator == (const T * other) const { return _ptr == other; }
|
||||||
|
@ -174,19 +221,16 @@ public:
|
||||||
|
|
||||||
inline operator bool() const { return _ptr != nullptr; }
|
inline operator bool() const { return _ptr != nullptr; }
|
||||||
|
|
||||||
inline T * get() const { return _ptr; }
|
|
||||||
|
|
||||||
inline void reset()
|
inline void reset()
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeReleaseRef(_ptr);
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
||||||
_ptr = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(RefPtr<T> & other)
|
inline void swap(RefPtr<T> & other)
|
||||||
{
|
{
|
||||||
if (&other != this)
|
if (&other != this)
|
||||||
{
|
{
|
||||||
T * tmp = _ptr;
|
Ref * tmp = _ptr;
|
||||||
_ptr = other._ptr;
|
_ptr = other._ptr;
|
||||||
other._ptr = tmp;
|
other._ptr = tmp;
|
||||||
}
|
}
|
||||||
|
@ -208,13 +252,12 @@ public:
|
||||||
*/
|
*/
|
||||||
inline void weakAssign(const RefPtr<T> & other)
|
inline void weakAssign(const RefPtr<T> & other)
|
||||||
{
|
{
|
||||||
RefPtrSupportFunctions::safeReleaseRef(_ptr);
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
||||||
_ptr = other._ptr;
|
_ptr = other._ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Ref * _ptr;
|
||||||
T * _ptr = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,6 +276,13 @@ template<class T, class U> RefPtr<T> dynamic_pointer_cast(const RefPtr<U> & r)
|
||||||
return RefPtr<T>(dynamic_cast<T*>(r.get()));
|
return RefPtr<T>(dynamic_cast<T*>(r.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Done with these macros.
|
||||||
|
*/
|
||||||
|
#undef CC_REF_PTR_SAFE_RETAIN
|
||||||
|
#undef CC_REF_PTR_SAFE_RELEASE
|
||||||
|
#undef CC_REF_PTR_SAFE_RELEASE_NULL
|
||||||
|
|
||||||
NS_CC_END
|
NS_CC_END
|
||||||
|
|
||||||
#endif // __CC_REF_PTR_H__
|
#endif // __CC_REF_PTR_H__
|
||||||
|
|
Loading…
Reference in New Issue