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(
const TfCallContext &,
const char *);
583 typedef typename boost::mpl::if_c<
584 Tf_SupportsUniqueChanged<T>::Value &&
585 !boost::is_convertible<T*, TfSimpleRefBase*>::value,
586 Tf_RefPtr_UniqueChangedCounter,
587 Tf_RefPtr_Counter>::type _Counter;
594 template <
class U>
struct Rebind {
604 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
614 p._refBase =
nullptr;
615 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
616 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
617 _GetObjectForTracking());
625 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
631 template <
template <
class>
class X,
class U>
632 inline TfRefPtr(
const TfWeakPtrFacade<X, U>& p,
633 typename boost::enable_if<
634 boost::is_convertible<U*, T*>
684 U* ptr,
typename std::enable_if<
685 std::is_convertible<U*, T*>::value>::type * =
nullptr) :
689 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
695 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
701 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
733 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
734 _GetObjectForTracking());
737 _refBase = p._refBase;
752 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
753 _GetObjectForTracking());
754 Tf_RefPtrTracker_Assign(&p,
nullptr,
755 p._GetObjectForTracking());
758 _refBase = p._refBase;
759 p._refBase =
nullptr;
770 Tf_RefPtrTracker_Delete(
this, _GetObjectForTracking());
771 _RemoveRef(_refBase);
778 static void _CheckTypeAssignability() {
780 if (unused) unused = 0;
785 static void _CheckTypeComparability() {
786 bool unused = ((T*)0 == (U*)0);
787 if (unused) unused =
false;
800 #if !defined(doxygen) 804 if (!boost::is_same<T,U>::value) {
806 _CheckTypeAssignability<U>();
810 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
823 #if !defined(doxygen) 827 if (!boost::is_same<T,U>::value) {
829 _CheckTypeAssignability<U>();
832 p._refBase =
nullptr;
833 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
834 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
835 _GetObjectForTracking());
848 #if !defined(doxygen) 852 if (!boost::is_same<T,U>::value) {
854 _CheckTypeAssignability<U>();
857 Tf_RefPtrTracker_Assign(
this,
858 reinterpret_cast<T*>(p._GetObjectForTracking()),
859 _GetObjectForTracking());
861 _refBase = p._GetData();
878 #if !defined(doxygen) 882 if (!boost::is_same<T,U>::value) {
884 _CheckTypeAssignability<U>();
887 Tf_RefPtrTracker_Assign(
this,
888 reinterpret_cast<T*>(p._GetObjectForTracking()),
889 _GetObjectForTracking());
890 Tf_RefPtrTracker_Assign(&p,
892 reinterpret_cast<T*>(p._GetObjectForTracking()));
894 _refBase = p._GetData();
895 p._refBase =
nullptr;
904 #if !defined(doxygen) 909 _CheckTypeComparability<U>();
911 return _refBase == p._refBase;
918 #if !defined(doxygen) 923 _CheckTypeComparability<U>();
925 return _refBase < p._refBase;
928 #if !defined(doxygen) 933 _CheckTypeComparability<U>();
935 return _refBase > p._refBase;
938 #if !defined(doxygen) 943 _CheckTypeComparability<U>();
945 return _refBase <= p._refBase;
948 #if !defined(doxygen) 953 _CheckTypeComparability<U>();
955 return _refBase >= p._refBase;
961 #if !defined(doxygen) 966 _CheckTypeComparability<U>();
968 return _refBase != p._refBase;
974 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
976 Tf_PostNullSmartPtrDereferenceFatalError(
977 TF_CALL_CONTEXT,
typeid(
TfRefPtr).name());
982 return *operator->();
985 #if !defined(doxygen) 990 operator UnspecifiedBoolType()
const {
991 return _refBase ? &TfRefPtr::_refBase :
nullptr;
996 return _refBase ==
nullptr;
1004 Tf_RefPtrTracker_Assign(
this, other._GetObjectForTracking(),
1005 _GetObjectForTracking());
1006 Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
1007 other._GetObjectForTracking());
1020 template <
class HashState,
class U>
1021 friend inline void TfHashAppend(HashState &,
const TfRefPtr<U>&);
1023 friend inline size_t hash_value(
const TfRefPtr<U>&);
1025 friend T *get_pointer(
TfRefPtr const &p) {
1026 return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
1030 class _CreateRefPtr { };
1037 Tf_RefPtrTracker_FirstRef(
this, _GetObjectForTracking());
1038 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
1059 #if defined(doxygen) 1064 template <
class D,
class B>
1068 template <
class D,
class B>
1089 #if defined(doxygen) 1094 template <
class D,
class B>
1111 #if defined(doxygen) 1121 T* _GetData()
const {
1122 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1131 T* _GetObjectForTracking()
const {
1132 return reinterpret_cast<T*>(const_cast<TfRefBase*>(_refBase));
1145 void _AddRef()
const {
1146 _Counter::AddRef(_refBase);
1149 void _RemoveRef(
const TfRefBase* ptr)
const {
1150 if (_Counter::RemoveRef(ptr)) {
1151 Tf_RefPtrTracker_LastRef(
this,
1152 reinterpret_cast<T*>(const_cast<TfRefBase*>(ptr)));
1157 #if ! defined(doxygen) 1160 template <
class U>
friend class TfRefPtr;
1161 template <
class U>
friend class TfWeakPtr;
1162 friend class Tf_Remnant;
1170 #if !defined(doxygen) 1193 return !(p ==
nullptr);
1198 return !(
nullptr == p);
1202 inline bool operator< (
const TfRefPtr<T> &p, std::nullptr_t)
1204 return std::less<const TfRefBase *>()(get_pointer(p),
nullptr);
1207 inline bool operator< (std::nullptr_t,
const TfRefPtr<T> &p)
1209 return std::less<const TfRefBase *>()(
nullptr, get_pointer(p));
1213 inline bool operator<= (
const TfRefPtr<T> &p, std::nullptr_t)
1215 return !(
nullptr < p);
1218 inline bool operator<= (std::nullptr_t,
const TfRefPtr<T> &p)
1220 return !(p <
nullptr);
1224 inline bool operator> (
const TfRefPtr<T> &p, std::nullptr_t)
1229 inline bool operator> (std::nullptr_t,
const TfRefPtr<T> &p)
1235 inline bool operator>= (
const TfRefPtr<T> &p, std::nullptr_t)
1237 return !(p <
nullptr);
1240 inline bool operator>= (std::nullptr_t,
const TfRefPtr<T> &p)
1242 return !(
nullptr < p);
1246 template <
typename T>
1252 const std::type_info&
1255 if (ARCH_UNLIKELY(!ptr._refBase))
1258 return typeid(*ptr._GetData());
1261 template <
class D,
class T>
1267 return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1270 template <
class D,
class T>
1276 return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1279 template <
class D,
class T>
1285 return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1296 return *((NonConstRefPtr*)(&ptr));
1318 return t.operator-> ();
1329 static void Class_Object_MUST_Be_Passed_By_Address() { }
1330 static void Class_Object_MUST_Not_Be_Const() { }
1336 return t.operator-> ();
1347 static void Class_Object_MUST_Be_Passed_By_Address() { }
1352 #if !defined(doxygen) 1361 PXR_NAMESPACE_CLOSE_SCOPE
1365 template<
typename T>
1367 get_pointer(PXR_NS::TfRefPtr<T>
const& p)
1369 return get_pointer(p);
1374 PXR_NAMESPACE_OPEN_SCOPE
1384 auto refBase = ptr._refBase;
1385 return boost::hash<decltype(refBase)>()(refBase);
1388 template <
class HashState,
class T>
1390 TfHashAppend(HashState &h,
const TfRefPtr<T> &ptr)
1392 h.Append(get_pointer(ptr));
1397 #define TF_SUPPORTS_REFPTR(T) boost::is_base_of<TfRefBase, T >::value 1399 #if defined(ARCH_COMPILER_MSVC) 1404 #define TF_REFPTR_CONST_VOLATILE_GET(x) \ 1409 get_pointer(const volatile x* p) \ 1415 #define TF_REFPTR_CONST_VOLATILE_GET(x) 1418 PXR_NAMESPACE_CLOSE_SCOPE
1420 #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.
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.
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
bool operator !() const
True if the pointer points to NULL.
Pointer storage with deletion detection.
Enable a concrete base class for use with TfRefPtr.
bool operator!=(const TfRefPtr< U > &p) const
Returns true if *this and p do not point to the same object.
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
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.
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.
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).
bool operator<(const TfRefPtr< U > &p) const
Returns true if the address of the object pointed to by *this compares less than the address of the o...
~TfRefPtr()
Decrements reference count of object being pointed to.
T & operator *() const
Dereferences the stored pointer.
std::enable_if< std::is_same< Half, half >::value, size_t >::type hash_value(const Half &h)
Overload hash_value for half.
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.
T * operator ->() const
Accessor to T's public members.
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.