24 #ifndef PXR_BASE_TF_REF_PTR_H
25 #define PXR_BASE_TF_REF_PTR_H
430 #include "pxr/base/tf/nullPtr.h"
434 #include "pxr/base/tf/api.h"
438 #include <boost/functional/hash_fwd.hpp>
439 #include <boost/mpl/if.hpp>
440 #include <boost/type_traits/is_base_of.hpp>
441 #include <boost/type_traits/is_convertible.hpp>
442 #include <boost/type_traits/is_same.hpp>
443 #include <boost/utility/enable_if.hpp>
446 #include <type_traits>
449 PXR_NAMESPACE_OPEN_SCOPE
455 struct Tf_SupportsUniqueChanged {
456 static const bool Value =
true;
462 struct Tf_SupportsUniqueChanged<Tf_Remnant> {
463 static const bool Value =
false;
469 template <
template <
class>
class X,
class Y>
470 class TfWeakPtrFacade;
473 inline void Tf_RefPtrTracker_FirstRef(
const void*,
const void*) { }
474 inline void Tf_RefPtrTracker_LastRef(
const void*,
const void*) { }
475 inline void Tf_RefPtrTracker_New(
const void*,
const void*) { }
476 inline void Tf_RefPtrTracker_Delete(
const void*,
const void*) { }
477 inline void Tf_RefPtrTracker_Assign(
const void*,
const void*,
const void*) { }
482 struct Tf_RefPtr_UniqueChangedCounter {
488 if (refBase->_shouldInvokeUniqueChangedListener)
489 return _AddRef(refBase);
491 return refBase->GetRefCount()._FetchAndAdd(1);
500 return refBase->_shouldInvokeUniqueChangedListener ?
501 _RemoveRef(refBase) :
502 refBase->GetRefCount()._DecrementAndTestIfZero();
513 if (ptr->_shouldInvokeUniqueChangedListener) {
514 return _AddRefIfNonzero(ptr);
516 auto &counter = ptr->GetRefCount()._counter;
517 auto val = counter.load();
521 }
while (!counter.compare_exchange_weak(val, val + 1));
526 TF_API
static bool _RemoveRef(
TfRefBase const *refBase);
528 TF_API
static int _AddRef(
TfRefBase const *refBase);
530 TF_API
static bool _AddRefIfNonzero(
TfRefBase const *refBase);
535 struct Tf_RefPtr_Counter {
539 return refBase->GetRefCount()._FetchAndAdd(1);
545 return (ptr && (ptr->GetRefCount()._DecrementAndTestIfZero()));
554 auto &counter = ptr->GetRefCount()._counter;
555 auto val = counter.load();
559 }
while (!counter.compare_exchange_weak(val, val + 1));
567 Tf_PostNullSmartPtrDereferenceFatalError(
568 const TfCallContext &,
const std::type_info &);
584 typedef typename boost::mpl::if_c<
585 Tf_SupportsUniqueChanged<T>::Value &&
586 !boost::is_convertible<T*, TfSimpleRefBase*>::value,
587 Tf_RefPtr_UniqueChangedCounter,
588 Tf_RefPtr_Counter>::type _Counter;
595 template <
class U>
struct Rebind {
605 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
615 p._refBase =
nullptr;
616 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
617 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
618 _GetObjectForTracking());
626 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
632 template <
template <
class>
class X,
class U>
633 inline TfRefPtr(
const TfWeakPtrFacade<X, U>& p,
634 typename boost::enable_if<
635 boost::is_convertible<U*, T*>
685 U* ptr,
typename std::enable_if<
686 std::is_convertible<U*, T*>::value>::type * =
nullptr) :
690 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
696 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
702 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
734 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
735 _GetObjectForTracking());
738 _refBase = p._refBase;
753 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
754 _GetObjectForTracking());
755 Tf_RefPtrTracker_Assign(&p,
nullptr,
756 p._GetObjectForTracking());
759 _refBase = p._refBase;
760 p._refBase =
nullptr;
771 Tf_RefPtrTracker_Delete(
this, _GetObjectForTracking());
772 _RemoveRef(_refBase);
779 static void _CheckTypeAssignability() {
781 if (unused) unused = 0;
786 static void _CheckTypeComparability() {
787 bool unused = ((T*)0 == (U*)0);
788 if (unused) unused =
false;
801 #if !defined(doxygen)
805 if (!boost::is_same<T,U>::value) {
807 _CheckTypeAssignability<U>();
811 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
824 #if !defined(doxygen)
828 if (!boost::is_same<T,U>::value) {
830 _CheckTypeAssignability<U>();
833 p._refBase =
nullptr;
834 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
835 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
836 _GetObjectForTracking());
849 #if !defined(doxygen)
853 if (!boost::is_same<T,U>::value) {
855 _CheckTypeAssignability<U>();
858 Tf_RefPtrTracker_Assign(
this,
859 reinterpret_cast<T*>(p._GetObjectForTracking()),
860 _GetObjectForTracking());
862 _refBase = p._GetData();
879 #if !defined(doxygen)
883 if (!boost::is_same<T,U>::value) {
885 _CheckTypeAssignability<U>();
888 Tf_RefPtrTracker_Assign(
this,
889 reinterpret_cast<T*>(p._GetObjectForTracking()),
890 _GetObjectForTracking());
891 Tf_RefPtrTracker_Assign(&p,
893 reinterpret_cast<T*>(p._GetObjectForTracking()));
895 _refBase = p._GetData();
896 p._refBase =
nullptr;
905 #if !defined(doxygen)
910 _CheckTypeComparability<U>();
912 return _refBase == p._refBase;
919 #if !defined(doxygen)
922 bool operator< (const TfRefPtr<U>& p)
const {
924 _CheckTypeComparability<U>();
926 return _refBase < p._refBase;
929 #if !defined(doxygen)
934 _CheckTypeComparability<U>();
936 return _refBase > p._refBase;
939 #if !defined(doxygen)
942 bool operator<= (const TfRefPtr<U>& p)
const {
944 _CheckTypeComparability<U>();
946 return _refBase <= p._refBase;
949 #if !defined(doxygen)
954 _CheckTypeComparability<U>();
956 return _refBase >= p._refBase;
962 #if !defined(doxygen)
967 _CheckTypeComparability<U>();
969 return _refBase != p._refBase;
974 if (ARCH_LIKELY(_refBase)) {
975 return static_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
977 static const TfCallContext ctx(TF_CALL_CONTEXT);
978 Tf_PostNullSmartPtrDereferenceFatalError(ctx,
typeid(
TfRefPtr));
986 #if !defined(doxygen)
991 operator UnspecifiedBoolType()
const {
992 return _refBase ? &TfRefPtr::_refBase :
nullptr;
997 return _refBase ==
nullptr;
1005 Tf_RefPtrTracker_Assign(
this, other._GetObjectForTracking(),
1006 _GetObjectForTracking());
1007 Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
1008 other._GetObjectForTracking());
1021 template <
class HashState,
class U>
1022 friend inline void TfHashAppend(HashState &,
const TfRefPtr<U>&);
1024 friend inline size_t hash_value(
const TfRefPtr<U>&);
1026 friend T *get_pointer(
TfRefPtr const &p) {
1027 return static_cast<T *
>(
const_cast<TfRefBase *
>(p._refBase));
1031 class _CreateRefPtr { };
1038 Tf_RefPtrTracker_FirstRef(
this, _GetObjectForTracking());
1039 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
1060 #if defined(doxygen)
1065 template <
class D,
class B>
1069 template <
class D,
class B>
1090 #if defined(doxygen)
1095 template <
class D,
class B>
1112 #if defined(doxygen)
1122 T* _GetData()
const {
1123 return static_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
1132 T* _GetObjectForTracking()
const {
1133 return reinterpret_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
1146 void _AddRef()
const {
1147 _Counter::AddRef(_refBase);
1150 void _RemoveRef(
const TfRefBase* ptr)
const {
1151 if (_Counter::RemoveRef(ptr)) {
1152 Tf_RefPtrTracker_LastRef(
this,
1153 reinterpret_cast<T*>(const_cast<TfRefBase*>(ptr)));
1158 #if ! defined(doxygen)
1161 template <
class U>
friend class TfRefPtr;
1162 template <
class U>
friend class TfWeakPtr;
1163 friend class Tf_Remnant;
1171 #if !defined(doxygen)
1194 return !(p ==
nullptr);
1199 return !(
nullptr == p);
1203 inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1205 return std::less<const TfRefBase *>()(get_pointer(p),
nullptr);
1208 inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1210 return std::less<const TfRefBase *>()(
nullptr, get_pointer(p));
1214 inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1216 return !(
nullptr < p);
1219 inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1221 return !(p <
nullptr);
1225 inline bool operator> (
const TfRefPtr<T> &p, std::nullptr_t)
1230 inline bool operator> (std::nullptr_t,
const TfRefPtr<T> &p)
1236 inline bool operator>= (
const TfRefPtr<T> &p, std::nullptr_t)
1238 return !(p <
nullptr);
1241 inline bool operator>= (std::nullptr_t,
const TfRefPtr<T> &p)
1243 return !(
nullptr < p);
1247 template <
typename T>
1253 const std::type_info&
1256 if (ARCH_UNLIKELY(!ptr._refBase))
1259 return typeid(*ptr._GetData());
1262 template <
class D,
class T>
1268 return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1271 template <
class D,
class T>
1277 return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1280 template <
class D,
class T>
1286 return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1297 return *((NonConstRefPtr*)(&ptr));
1319 return t.operator-> ();
1330 static void Class_Object_MUST_Be_Passed_By_Address() { }
1331 static void Class_Object_MUST_Not_Be_Const() { }
1337 return t.operator-> ();
1348 static void Class_Object_MUST_Be_Passed_By_Address() { }
1353 #if !defined(doxygen)
1362 PXR_NAMESPACE_CLOSE_SCOPE
1366 template<
typename T>
1368 get_pointer(PXR_NS::TfRefPtr<T>
const& p)
1370 return get_pointer(p);
1375 PXR_NAMESPACE_OPEN_SCOPE
1385 auto refBase = ptr._refBase;
1386 return boost::hash<decltype(refBase)>()(refBase);
1389 template <
class HashState,
class T>
1391 TfHashAppend(HashState &h,
const TfRefPtr<T> &ptr)
1393 h.Append(get_pointer(ptr));
1398 #define TF_SUPPORTS_REFPTR(T) boost::is_base_of<TfRefBase, T >::value
1400 #if defined(ARCH_COMPILER_MSVC)
1405 #define TF_REFPTR_CONST_VOLATILE_GET(x) \
1410 get_pointer(const volatile x* p) \
1416 #define TF_REFPTR_CONST_VOLATILE_GET(x)
1419 PXR_NAMESPACE_CLOSE_SCOPE
1421 #endif // PXR_BASE_TF_REF_PTR_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
TfRefPtr()
Initialize pointer to nullptr.
TfRefPtr< T > & operator=(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object. ...
bool operator!() const
True if the pointer points to NULL.
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
TO TfSafeDynamic_cast(FROM *ptr)
Safely perform a dynamic cast.
void Reset()
Set this pointer to point to no object.
Safely compare C++ RTTI type structures.
TfRefPtr(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object. ...
friend TfRef< D > TfDynamic_cast(const TfRefPtr< T > &)
Allows dynamic casting of a TfRefPtr.
TfRefPtr< T > & operator=(const TfRefPtr< U > &p)
Assigns pointer to point at p's object, and increments reference count.
SdfHandle< typename DST::SpecType > TfStatic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle<SRC> x to an SdfHandle<DST>.
AR_API bool operator!=(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
T DataType
Convenience type accessor to underlying type T for template code.
void swap(TfRefPtr &other)
Swap this pointer with other.
bool operator==(const TfRefPtr< U > &p) const
Returns true if *this and p point to the same object (or if they both point to NULL).
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
Pointer storage with deletion detection.
Enable a concrete base class for use with TfRefPtr.
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
T * operator->() const
Accessor to T's public members.
SdfHandle< typename DST::SpecType > TfDynamic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle<SRC> x to an SdfHandle<DST>.
void swap(UsdStageLoadRules &l, UsdStageLoadRules &r)
Swap the contents of rules l and r.
bool operator!=(const TfRefPtr< U > &p) const
Returns true if *this and p do not point to the same object.
TfRefPtr< T > & operator=(const TfRefPtr< T > &p)
Assigns pointer to point at p's object, and increments reference count.
friend const std::type_info & TfTypeid(const TfRefPtr< U > &ptr)
Call typeid on the object pointed to by a TfRefPtr.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
TfRefPtr(const TfRefPtr< U > &p)
Initializes to point at p's object, and increments reference count.
~TfRefPtr()
Decrements reference count of object being pointed to.
T & operator*() const
Dereferences the stored pointer.
friend TfRefPtr TfCreateRefPtr(T *)
Transfer a raw pointer to a reference-counted pointer.
TfRefPtr< T > & operator=(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object. ...
friend TfRefPtr< D > TfConst_cast(const TfRefPtr< const D > &)
Allows const casting of a TfRefPtr.
Implements assorted functions based on compile-time type information.
friend TfRefPtr< D > TfStatic_cast(const TfRefPtr< T > &)
Allows static casting of a TfRefPtr.
Reference-counted smart pointer utility class.
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
Enable a concrete base class for use with TfWeakPtr.
Stripped down version of diagnostic.h that doesn't define std::string.