From f147ef723a8a459b3a05ab51eae7460dc922a16c Mon Sep 17 00:00:00 2001 From: Darragh Coy Date: Mon, 7 Apr 2014 16:04:00 -0700 Subject: [PATCH] Merge the alternate RefPtr 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. --- .../project.pbxproj.REMOVED.git-id | 2 +- cocos/base/CCRefPtr.cpp | 51 -------- cocos/base/CCRefPtr.h | 118 +++++++++++++----- 3 files changed, 85 insertions(+), 86 deletions(-) delete mode 100644 cocos/base/CCRefPtr.cpp diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index f8f068ce4c..517324a4e4 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -f722a4d89963f2d2a58b754e12d1baa2bf0c5ece \ No newline at end of file +a6890abb8134492d61129c585fbd28941e825a6f \ No newline at end of file diff --git a/cocos/base/CCRefPtr.cpp b/cocos/base/CCRefPtr.cpp deleted file mode 100644 index 0cea720a83..0000000000 --- a/cocos/base/CCRefPtr.cpp +++ /dev/null @@ -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(const_cast(refPtr)); - CC_ASSERT(dynamic_cast(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(const_cast(refPtr)); - CC_ASSERT(dynamic_cast(refPtrCast)); // Check for invalid type pointed to in RefPtr. Object pointed to must be a cocos2d::Ref! - refPtrCast->release(); - } -} - -NS_CC_END diff --git a/cocos/base/CCRefPtr.h b/cocos/base/CCRefPtr.h index 4ffba53bbf..e8906aadf3 100644 --- a/cocos/base/CCRefPtr.h +++ b/cocos/base/CCRefPtr.h @@ -26,23 +26,48 @@ #ifndef __CC_REF_PTR_H__ #define __CC_REF_PTR_H__ -#include "CCPlatformMacros.h" -#include "ccConfig.h" +#include "CCRef.h" #include NS_CC_BEGIN -class Ref; - /** - * Utility/support functions for RefPtr. + * Utility/support macros. Defined to enable RefPtr 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(static_cast(ptr))->retain();\ + }\ + \ + } while (0); + +#define CC_REF_PTR_SAFE_RELEASE(ptr)\ + \ + do\ + {\ + if (ptr)\ + {\ + const_cast(static_cast(ptr))->release();\ + }\ + \ + } while (0); + +#define CC_REF_PTR_SAFE_RELEASE_NULL(ptr)\ + \ + do\ + {\ + if (ptr)\ + {\ + const_cast(static_cast(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 class RefPtr { public: + RefPtr() + : _ptr(nullptr) + { + } - RefPtr() = default; - inline RefPtr(T * ptr) : - _ptr(ptr) + _ptr(const_cast::type*>(ptr)) // Const cast allows RefPtr 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 & 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 & 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::type*>(other); // Const cast allows RefPtr 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(_ptr); } inline T & operator * () const { CCASSERT(_ptr, "Attempt to dereference a null pointer!"); - return *_ptr; + return reinterpret_cast(*_ptr); } inline T * operator->() const { CCASSERT(_ptr, "Attempt to dereference a null pointer!"); - return _ptr; + return reinterpret_cast(_ptr); } + inline T * get() const { return reinterpret_cast(_ptr); } + + inline bool operator == (const RefPtr & 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 & 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 & other) { - RefPtrSupportFunctions::safeReleaseRef(_ptr); + CC_REF_PTR_SAFE_RELEASE(_ptr); _ptr = other._ptr; } private: - - T * _ptr = nullptr; + Ref * _ptr; }; /** @@ -233,6 +276,13 @@ template RefPtr dynamic_pointer_cast(const RefPtr & r) return RefPtr(dynamic_cast(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__