2014-03-27 06:30:15 +08:00
|
|
|
/****************************************************************************
|
2015-03-24 20:23:51 +08:00
|
|
|
Copyright (c) 2014 PlayFirst Inc.
|
2016-08-05 09:42:15 +08:00
|
|
|
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __CC_REF_PTR_H__
|
|
|
|
#define __CC_REF_PTR_H__
|
2015-03-24 20:23:51 +08:00
|
|
|
/// @cond DO_NOT_SHOW
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2014-04-27 01:11:22 +08:00
|
|
|
#include "base/CCRef.h"
|
2014-04-30 08:37:36 +08:00
|
|
|
#include "base/ccMacros.h"
|
2016-05-28 21:15:56 +08:00
|
|
|
#include <functional>
|
2014-03-27 06:30:15 +08:00
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
|
|
|
/**
|
2014-04-08 07:04:00 +08:00
|
|
|
* 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.
|
2014-03-27 06:30:15 +08:00
|
|
|
*/
|
2014-04-08 07:04:00 +08:00
|
|
|
#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);
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper class which maintains a strong reference to a cocos2dx cocos2d::Ref* type object.
|
|
|
|
* Similar in concept to a boost smart pointer.
|
|
|
|
*
|
|
|
|
* Enables the use of the RAII idiom with Cocos2dx objects and helps automate some of the more
|
|
|
|
* mundane tasks of pointer initialization and cleanup.
|
|
|
|
*
|
|
|
|
* The class itself is modelled on C++ 11 std::shared_ptr, and trys to keep some of the methods
|
|
|
|
* and functionality consistent with std::shared_ptr.
|
|
|
|
*/
|
|
|
|
template <typename T> class RefPtr
|
|
|
|
{
|
|
|
|
public:
|
2014-04-09 02:34:27 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr()
|
2016-06-26 20:39:43 +08:00
|
|
|
: _ptr(nullptr)
|
2014-04-09 02:44:54 +08:00
|
|
|
{
|
2014-04-09 02:34:27 +08:00
|
|
|
|
2014-04-09 02:44:54 +08:00
|
|
|
}
|
2014-04-09 02:34:27 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr(RefPtr<T> && other)
|
2014-04-09 02:34:27 +08:00
|
|
|
{
|
|
|
|
_ptr = other._ptr;
|
|
|
|
other._ptr = nullptr;
|
|
|
|
}
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr(T * ptr)
|
2016-06-26 20:39:43 +08:00
|
|
|
: _ptr(ptr)
|
2014-04-08 07:04:00 +08:00
|
|
|
{
|
|
|
|
CC_REF_PTR_SAFE_RETAIN(_ptr);
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr(std::nullptr_t ptr)
|
2016-06-26 20:39:43 +08:00
|
|
|
: _ptr(nullptr)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr(const RefPtr<T> & other)
|
2016-06-26 20:39:43 +08:00
|
|
|
: _ptr(other._ptr)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RETAIN(_ptr);
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
~RefPtr()
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr<T> & operator = (const RefPtr<T> & other)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
|
|
|
if (other._ptr != _ptr)
|
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RETAIN(other._ptr);
|
|
|
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
2014-03-27 06:30:15 +08:00
|
|
|
_ptr = other._ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr<T> & operator = (RefPtr<T> && other)
|
2014-04-08 07:04:00 +08:00
|
|
|
{
|
2014-04-09 02:34:27 +08:00
|
|
|
if (&other != this)
|
|
|
|
{
|
|
|
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
|
|
|
_ptr = other._ptr;
|
|
|
|
other._ptr = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-04-08 07:04:00 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr<T> & operator = (T * other)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
|
|
|
if (other != _ptr)
|
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RETAIN(other);
|
|
|
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
2016-06-26 20:39:43 +08:00
|
|
|
_ptr = other;
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
RefPtr<T> & operator = (std::nullptr_t other)
|
2014-04-09 02:34:27 +08:00
|
|
|
{
|
|
|
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
operator T * () const { return _ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
T & operator * () const
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
|
|
|
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
2016-06-26 20:39:43 +08:00
|
|
|
return *_ptr;
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
T * operator->() const
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
|
|
|
CCASSERT(_ptr, "Attempt to dereference a null pointer!");
|
2016-06-26 20:39:43 +08:00
|
|
|
return _ptr;
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
T * get() const { return _ptr; }
|
2014-04-08 07:04:00 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator == (const RefPtr<T> & other) const { return _ptr == other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator == (const T * other) const { return _ptr == other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator == (typename std::remove_const<T>::type * other) const { return _ptr == other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator == (const std::nullptr_t other) const { return _ptr == other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator != (const RefPtr<T> & other) const { return _ptr != other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator != (const T * other) const { return _ptr != other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator != (typename std::remove_const<T>::type * other) const { return _ptr != other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator != (const std::nullptr_t other) const { return _ptr != other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator > (const RefPtr<T> & other) const { return _ptr > other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator > (const T * other) const { return _ptr > other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator > (typename std::remove_const<T>::type * other) const { return _ptr > other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator < (const RefPtr<T> & other) const { return _ptr < other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator < (const T * other) const { return _ptr < other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator < (typename std::remove_const<T>::type * other) const { return _ptr < other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator >= (const RefPtr<T> & other) const { return _ptr >= other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator >= (const T * other) const { return _ptr >= other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator >= (typename std::remove_const<T>::type * other) const { return _ptr >= other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator <= (const RefPtr<T> & other) const { return _ptr <= other._ptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator <= (const T * other) const { return _ptr <= other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
bool operator <= (typename std::remove_const<T>::type * other) const { return _ptr <= other; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
operator bool() const { return _ptr != nullptr; }
|
2014-03-27 06:30:15 +08:00
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
void reset()
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
|
2014-03-27 06:30:15 +08:00
|
|
|
}
|
|
|
|
|
2016-09-12 09:44:21 +08:00
|
|
|
void swap(RefPtr<T> & other)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
|
|
|
if (&other != this)
|
|
|
|
{
|
2016-06-26 20:39:43 +08:00
|
|
|
T * tmp = _ptr;
|
2014-03-27 06:30:15 +08:00
|
|
|
_ptr = other._ptr;
|
|
|
|
other._ptr = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function assigns to this RefPtr<T> but does not increase the reference count of the object pointed to.
|
|
|
|
* Useful for assigning an object created through the 'new' operator to a RefPtr<T>. Basically used in scenarios
|
|
|
|
* where the RefPtr<T> has the initial ownership of the object.
|
|
|
|
*
|
|
|
|
* E.G:
|
|
|
|
* RefPtr<cocos2d::Image> image;
|
|
|
|
* image.weakAssign(new cocos2d::Image());
|
|
|
|
*
|
|
|
|
* Instead of:
|
|
|
|
* RefPtr<cocos2d::Image> image;
|
|
|
|
* image = new cocos2d::Image();
|
|
|
|
* image->release(); // Required because new'd object already has a reference count of '1'.
|
|
|
|
*/
|
2016-09-12 09:44:21 +08:00
|
|
|
void weakAssign(const RefPtr<T> & other)
|
2014-03-27 06:30:15 +08:00
|
|
|
{
|
2014-04-08 07:04:00 +08:00
|
|
|
CC_REF_PTR_SAFE_RELEASE(_ptr);
|
2014-03-27 06:30:15 +08:00
|
|
|
_ptr = other._ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-06-26 20:39:43 +08:00
|
|
|
T * _ptr;
|
|
|
|
|
|
|
|
// NOTE: We can ensure T is derived from cocos2d::Ref at compile time here.
|
|
|
|
static_assert(std::is_base_of<Ref, typename std::remove_const<T>::type>::value, "T must be derived from Ref");
|
2014-03-27 06:30:15 +08:00
|
|
|
};
|
|
|
|
|
2016-05-28 21:15:56 +08:00
|
|
|
template<class T> inline
|
|
|
|
bool operator<(const RefPtr<T>& r, std::nullptr_t)
|
|
|
|
{
|
|
|
|
return std::less<T*>()(r.get(), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator<(std::nullptr_t, const RefPtr<T>& r)
|
|
|
|
{
|
|
|
|
return std::less<T*>()(nullptr, r.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator>(const RefPtr<T>& r, std::nullptr_t)
|
|
|
|
{
|
|
|
|
return nullptr < r;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator>(std::nullptr_t, const RefPtr<T>& r)
|
|
|
|
{
|
|
|
|
return r < nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator<=(const RefPtr<T>& r, std::nullptr_t)
|
|
|
|
{
|
|
|
|
return !(nullptr < r);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator<=(std::nullptr_t, const RefPtr<T>& r)
|
|
|
|
{
|
|
|
|
return !(r < nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator>=(const RefPtr<T>& r, std::nullptr_t)
|
|
|
|
{
|
|
|
|
return !(r < nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T> inline
|
|
|
|
bool operator>=(std::nullptr_t, const RefPtr<T>& r)
|
|
|
|
{
|
|
|
|
return !(nullptr < r);
|
|
|
|
}
|
|
|
|
|
2014-03-27 06:30:15 +08:00
|
|
|
/**
|
|
|
|
* Cast between RefPtr types statically.
|
|
|
|
*/
|
|
|
|
template<class T, class U> RefPtr<T> static_pointer_cast(const RefPtr<U> & r)
|
|
|
|
{
|
|
|
|
return RefPtr<T>(static_cast<T*>(r.get()));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cast between RefPtr types dynamically.
|
|
|
|
*/
|
|
|
|
template<class T, class U> RefPtr<T> dynamic_pointer_cast(const RefPtr<U> & r)
|
|
|
|
{
|
|
|
|
return RefPtr<T>(dynamic_cast<T*>(r.get()));
|
|
|
|
}
|
|
|
|
|
2014-04-08 07:04:00 +08:00
|
|
|
/**
|
|
|
|
* Done with these macros.
|
|
|
|
*/
|
|
|
|
#undef CC_REF_PTR_SAFE_RETAIN
|
|
|
|
#undef CC_REF_PTR_SAFE_RELEASE
|
|
|
|
#undef CC_REF_PTR_SAFE_RELEASE_NULL
|
|
|
|
|
2014-03-27 06:30:15 +08:00
|
|
|
NS_CC_END
|
|
|
|
|
2015-03-24 20:23:51 +08:00
|
|
|
/// @endcond
|
2014-03-27 06:30:15 +08:00
|
|
|
#endif // __CC_REF_PTR_H__
|