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:
Darragh Coy 2014-04-07 16:04:00 -07:00
parent 586383a05e
commit f147ef723a
3 changed files with 85 additions and 86 deletions

View File

@ -1 +1 @@
f722a4d89963f2d2a58b754e12d1baa2bf0c5ece
a6890abb8134492d61129c585fbd28941e825a6f

View File

@ -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

View File

@ -26,23 +26,48 @@
#ifndef __CC_REF_PTR_H__
#define __CC_REF_PTR_H__
#include "CCPlatformMacros.h"
#include "ccConfig.h"
#include "CCRef.h"
#include <type_traits>
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
{
void safeRetainRef(const void * refPtr);
void safeReleaseRef(const void * refPtr);
}
#define CC_REF_PTR_SAFE_RETAIN(ptr)\
\
do\
{\
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.
@ -57,67 +82,89 @@ namespace RefPtrSupportFunctions
template <typename T> class RefPtr
{
public:
RefPtr()
: _ptr(nullptr)
{
}
RefPtr() = default;
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)
:
_ptr(other._ptr)
{
RefPtrSupportFunctions::safeRetainRef(_ptr);
CC_REF_PTR_SAFE_RETAIN(_ptr);
}
inline ~RefPtr()
{
RefPtrSupportFunctions::safeReleaseRef(_ptr);
_ptr = nullptr;
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
}
inline RefPtr & operator = (const RefPtr<T> & other)
{
if (other._ptr != _ptr)
{
RefPtrSupportFunctions::safeRetainRef(other._ptr);
RefPtrSupportFunctions::safeReleaseRef(_ptr);
CC_REF_PTR_SAFE_RETAIN(other._ptr);
CC_REF_PTR_SAFE_RELEASE(_ptr);
_ptr = other._ptr;
}
return *this;
}
inline RefPtr & operator = (std::nullptr_t other)
{
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
return *this;
}
inline RefPtr & operator = (T * other)
{
if (other != _ptr)
{
RefPtrSupportFunctions::safeRetainRef(other);
RefPtrSupportFunctions::safeReleaseRef(_ptr);
_ptr = other;
CC_REF_PTR_SAFE_RETAIN(other);
CC_REF_PTR_SAFE_RELEASE(_ptr);
_ptr = const_cast<typename std::remove_const<T>::type*>(other); // Const cast allows RefPtr<T> to reference objects marked const too.
}
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
{
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
return *_ptr;
return reinterpret_cast<T&>(*_ptr);
}
inline T * operator->() const
{
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 T * other) const { return _ptr == other; }
@ -174,19 +221,16 @@ public:
inline operator bool() const { return _ptr != nullptr; }
inline T * get() const { return _ptr; }
inline void reset()
{
RefPtrSupportFunctions::safeReleaseRef(_ptr);
_ptr = nullptr;
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
}
inline void swap(RefPtr<T> & other)
{
if (&other != this)
{
T * tmp = _ptr;
Ref * tmp = _ptr;
_ptr = other._ptr;
other._ptr = tmp;
}
@ -208,13 +252,12 @@ public:
*/
inline void weakAssign(const RefPtr<T> & other)
{
RefPtrSupportFunctions::safeReleaseRef(_ptr);
CC_REF_PTR_SAFE_RELEASE(_ptr);
_ptr = other._ptr;
}
private:
T * _ptr = nullptr;
Ref * _ptr;
};
/**
@ -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()));
}
/**
* 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
#endif // __CC_REF_PTR_H__