24#ifndef PXR_BASE_TF_REF_PTR_H
25#define PXR_BASE_TF_REF_PTR_H
431#include "pxr/base/tf/nullPtr.h"
435#include "pxr/base/tf/api.h"
441#include <type_traits>
444PXR_NAMESPACE_OPEN_SCOPE
450struct Tf_SupportsUniqueChanged {
451 static const bool Value =
true;
457struct Tf_SupportsUniqueChanged<Tf_Remnant> {
458 static const bool Value =
false;
464template <
template <
class>
class X,
class Y>
465class TfWeakPtrFacade;
468inline void Tf_RefPtrTracker_FirstRef(
const void*,
const void*) { }
469inline void Tf_RefPtrTracker_LastRef(
const void*,
const void*) { }
470inline void Tf_RefPtrTracker_New(
const void*,
const void*) { }
471inline void Tf_RefPtrTracker_Delete(
const void*,
const void*) { }
472inline void Tf_RefPtrTracker_Assign(
const void*,
const void*,
const void*) { }
477struct Tf_RefPtr_UniqueChangedCounter {
480 if (ARCH_UNLIKELY(!refBase)) {
483 const auto relaxed = std::memory_order_relaxed;
485 std::atomic_int &counter = refBase->_GetRefCount();
486 int prevCount = counter.load(relaxed);
487 if (ARCH_UNLIKELY(prevCount < 0)) {
493 if (prevCount != -1 && counter.
494 compare_exchange_weak(prevCount, prevCount-1, relaxed)) {
497 _AddRefMaybeLocked(refBase, prevCount);
501 counter.fetch_add(1, relaxed);
507 if (ARCH_UNLIKELY(!refBase)) {
510 const auto relaxed = std::memory_order_relaxed;
511 const auto release = std::memory_order_release;
513 std::atomic_int &counter = refBase->_GetRefCount();
514 int prevCount = counter.load(relaxed);
515 if (ARCH_UNLIKELY(prevCount < 0)) {
521 if (prevCount != -2 && counter.
522 compare_exchange_weak(prevCount, prevCount+1, release)) {
523 return prevCount == -1;
525 return _RemoveRefMaybeLocked(refBase, prevCount);
529 return counter.fetch_sub(1, release) == 1;
536 AddRefIfNonzero(
TfRefBase const *refBase);
539 _AddRefMaybeLocked(
TfRefBase const *refBase,
int prevCount);
542 _RemoveRefMaybeLocked(
TfRefBase const *refBase,
int prevCount);
548struct Tf_RefPtr_Counter {
551 if (ARCH_UNLIKELY(!refBase)) {
554 refBase->_GetRefCount().fetch_add(1, std::memory_order_relaxed);
559 if (ARCH_UNLIKELY(!refBase)) {
562 return refBase->_GetRefCount()
563 .fetch_sub(1, std::memory_order_release) == 1;
569 AddRefIfNonzero(
TfRefBase const *refBase) {
570 if (ARCH_UNLIKELY(!refBase)) {
573 auto &counter = refBase->_GetRefCount();
574 int prevCount = counter.load(std::memory_order_relaxed);
576 if (counter.compare_exchange_weak(prevCount, prevCount+1)) {
587Tf_PostNullSmartPtrDereferenceFatalError(
const TfCallContext &,
const char *);
603 using _Counter =
typename std::conditional<
604 Tf_SupportsUniqueChanged<T>::Value &&
605 !std::is_convertible<T*, TfSimpleRefBase*>::value,
606 Tf_RefPtr_UniqueChangedCounter,
607 Tf_RefPtr_Counter>::type;
614 template <
class U>
struct Rebind {
624 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
634 p._refBase =
nullptr;
635 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
636 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
637 _GetObjectForTracking());
645 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
651 template <
template <
class>
class X,
class U>
652 inline TfRefPtr(
const TfWeakPtrFacade<X, U>& p,
653 typename std::enable_if<
654 std::is_convertible<U*, T*>::value
704 U* ptr,
typename std::enable_if<
705 std::is_convertible<U*, T*>::value>::type * =
nullptr) :
709 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
715 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
721 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
753 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
754 _GetObjectForTracking());
757 _refBase = p._refBase;
772 Tf_RefPtrTracker_Assign(
this, p._GetObjectForTracking(),
773 _GetObjectForTracking());
774 Tf_RefPtrTracker_Assign(&p,
nullptr,
775 p._GetObjectForTracking());
778 _refBase = p._refBase;
779 p._refBase =
nullptr;
790 Tf_RefPtrTracker_Delete(
this, _GetObjectForTracking());
791 _RemoveRef(_refBase);
806 static_assert(std::is_convertible<U*, T*>::value,
"");
808 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
825 static_assert(std::is_convertible<U*, T*>::value,
"");
826 p._refBase =
nullptr;
827 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
828 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
829 _GetObjectForTracking());
846 static_assert(std::is_convertible<U*, T*>::value,
"");
848 Tf_RefPtrTracker_Assign(
this,
849 reinterpret_cast<T*
>(p._GetObjectForTracking()),
850 _GetObjectForTracking());
852 _refBase = p._GetData();
873 static_assert(std::is_convertible<U*, T*>::value,
"");
875 Tf_RefPtrTracker_Assign(
this,
876 reinterpret_cast<T*
>(p._GetObjectForTracking()),
877 _GetObjectForTracking());
878 Tf_RefPtrTracker_Assign(&p,
880 reinterpret_cast<T*
>(p._GetObjectForTracking()));
882 _refBase = p._GetData();
883 p._refBase =
nullptr;
896 ->
decltype(std::declval<T *>() == std::declval<U *>(), bool()) {
897 return _refBase == p._refBase;
907 ->
decltype(std::declval<T *>() != std::declval<U *>(), bool()) {
908 return _refBase != p._refBase;
919 ->
decltype(std::declval<T *>() < std::declval<U *>(), bool()) {
920 return _refBase < p._refBase;
927 ->
decltype(std::declval<T *>() > std::declval<U *>(), bool()) {
928 return _refBase > p._refBase;
935 ->
decltype(std::declval<T *>() <= std::declval<U *>(), bool()) {
936 return _refBase <= p._refBase;
943 ->
decltype(std::declval<T *>() >= std::declval<U *>(), bool()) {
944 return _refBase >= p._refBase;
950 return static_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
952 Tf_PostNullSmartPtrDereferenceFatalError(
953 TF_CALL_CONTEXT,
typeid(
TfRefPtr).name());
966 operator UnspecifiedBoolType()
const {
967 return _refBase ? &TfRefPtr::_refBase :
nullptr;
972 return _refBase ==
nullptr;
980 Tf_RefPtrTracker_Assign(
this, other._GetObjectForTracking(),
981 _GetObjectForTracking());
982 Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
983 other._GetObjectForTracking());
984 std::swap(_refBase, other._refBase);
996 template <
class HashState,
class U>
997 friend inline void TfHashAppend(HashState &,
const TfRefPtr<U>&);
999 friend inline size_t hash_value(
const TfRefPtr<U>&);
1001 friend T *get_pointer(
TfRefPtr const &p) {
1002 return static_cast<T *
>(
const_cast<TfRefBase *
>(p._refBase));
1006 class _CreateRefPtr { };
1013 Tf_RefPtrTracker_FirstRef(
this, _GetObjectForTracking());
1014 Tf_RefPtrTracker_New(
this, _GetObjectForTracking());
1040 template <
class D,
class B>
1044 template <
class D,
class B>
1070 template <
class D,
class B>
1097 T* _GetData()
const {
1098 return static_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
1107 T* _GetObjectForTracking()
const {
1108 return reinterpret_cast<T*
>(
const_cast<TfRefBase*
>(_refBase));
1121 void _AddRef()
const {
1122 _Counter::AddRef(_refBase);
1125 void _RemoveRef(
const TfRefBase* ptr)
const {
1126 if (_Counter::RemoveRef(ptr)) {
1127 Tf_RefPtrTracker_LastRef(
this,
1128 reinterpret_cast<T*
>(
const_cast<TfRefBase*
>(ptr)));
1133#if ! defined(doxygen)
1136 template <
class U>
friend class TfRefPtr;
1137 template <
class U>
friend class TfWeakPtr;
1138 friend class Tf_Remnant;
1146#if !defined(doxygen)
1156inline bool operator== (
const TfRefPtr<T> &p, std::nullptr_t)
1161inline bool operator== (std::nullptr_t,
const TfRefPtr<T> &p)
1167inline bool operator!= (
const TfRefPtr<T> &p, std::nullptr_t)
1169 return !(p ==
nullptr);
1172inline bool operator!= (std::nullptr_t,
const TfRefPtr<T> &p)
1174 return !(
nullptr == p);
1178inline bool operator< (
const TfRefPtr<T> &p, std::nullptr_t)
1180 return std::less<const TfRefBase *>()(get_pointer(p),
nullptr);
1183inline bool operator< (std::nullptr_t,
const TfRefPtr<T> &p)
1185 return std::less<const TfRefBase *>()(
nullptr, get_pointer(p));
1189inline bool operator<= (
const TfRefPtr<T> &p, std::nullptr_t)
1191 return !(
nullptr < p);
1194inline bool operator<= (std::nullptr_t,
const TfRefPtr<T> &p)
1196 return !(p <
nullptr);
1200inline bool operator> (
const TfRefPtr<T> &p, std::nullptr_t)
1205inline bool operator> (std::nullptr_t,
const TfRefPtr<T> &p)
1211inline bool operator>= (
const TfRefPtr<T> &p, std::nullptr_t)
1213 return !(p <
nullptr);
1216inline bool operator>= (std::nullptr_t,
const TfRefPtr<T> &p)
1218 return !(
nullptr < p);
1222template <
typename T>
1228const std::type_info&
1231 if (ARCH_UNLIKELY(!ptr._refBase))
1234 return typeid(*ptr._GetData());
1237template <
class D,
class T>
1243 return RefPtr(
dynamic_cast<typename D::DataType*
>(ptr._GetData()));
1246template <
class D,
class T>
1252 return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1255template <
class D,
class T>
1261 return RefPtr(
static_cast<typename D::DataType*
>(ptr._GetData()));
1272 return *((NonConstRefPtr*)(&ptr));
1292 return t.operator-> ();
1303 static void Class_Object_MUST_Be_Passed_By_Address() { }
1304 static void Class_Object_MUST_Not_Be_Const() { }
1310 return t.operator-> ();
1321 static void Class_Object_MUST_Be_Passed_By_Address() { }
1326#if !defined(doxygen)
1335PXR_NAMESPACE_CLOSE_SCOPE
1341get_pointer(PXR_NS::TfRefPtr<T>
const& p)
1343 return get_pointer(p);
1348PXR_NAMESPACE_OPEN_SCOPE
1358template <
class HashState,
class T>
1362 h.Append(get_pointer(ptr));
1367#define TF_SUPPORTS_REFPTR(T) std::is_base_of_v<TfRefBase, T>
1369PXR_NAMESPACE_CLOSE_SCOPE
A user-extensible hashing mechanism for use with runtime hash tables.
Enable a concrete base class for use with TfRefPtr.
Reference-counted smart pointer utility class.
TfRefPtr< T > & operator=(const TfRefPtr< T > &p)
Assigns pointer to point at p's object, and increments reference count.
T & operator*() const
Dereferences the stored pointer.
TfRefPtr< T > & operator=(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
auto operator==(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >()==std::declval< U * >(), bool())
Returns true if *this and p point to the same object (or if they both point to NULL).
friend TfRefPtr< D > TfConst_cast(const TfRefPtr< const D > &)
Allows const casting of a TfRefPtr.
TfRefPtr< T > & operator=(const TfRefPtr< U > &p)
Assigns pointer to point at p's object, and increments reference count.
void Reset()
Set this pointer to point to no object.
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
friend const std::type_info & TfTypeid(const TfRefPtr< U > &ptr)
Call typeid on the object pointed to by a TfRefPtr.
~TfRefPtr()
Decrements reference count of object being pointed to.
bool operator!() const
True if the pointer points to NULL.
void swap(TfRefPtr &other)
Swap this pointer with other.
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
T * operator->() const
Accessor to T's public members.
friend TfRefPtr TfCreateRefPtr(T *)
Transfer a raw pointer to a reference-counted pointer.
friend TfRefPtr< D > TfStatic_cast(const TfRefPtr< T > &)
Allows static casting of a TfRefPtr.
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
TfRefPtr< T > & operator=(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
auto operator!=(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >() !=std::declval< U * >(), bool())
Returns true if *this and p do not point to the same object.
friend TfRefPtr< D > TfDynamic_cast(const TfRefPtr< T > &)
Allows dynamic casting of a TfRefPtr.
TfRefPtr()
Initialize pointer to nullptr.
TfRefPtr(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
TfRefPtr(const TfRefPtr< U > &p)
Initializes to point at p's object, and increments reference count.
auto operator<(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >()< std::declval< U * >(), bool())
Returns true if the address of the object pointed to by *this compares less than the address of the o...
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
T DataType
Convenience type accessor to underlying type T for template code.
Enable a concrete base class for use with TfWeakPtr.
Pointer storage with deletion detection.
Stripped down version of diagnostic.h that doesn't define std::string.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Safely compare C++ RTTI type structures.
TO TfSafeDynamic_cast(FROM *ptr)
Safely perform a dynamic cast.
Implements assorted functions based on compile-time type information.
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.