Loading...
Searching...
No Matches
refPtr.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_REF_PTR_H
8#define PXR_BASE_TF_REF_PTR_H
9
409
410#include "pxr/pxr.h"
411
413#include "pxr/base/tf/hash.h"
414#include "pxr/base/tf/nullPtr.h"
415#include "pxr/base/tf/refBase.h"
418#include "pxr/base/tf/api.h"
419
420#include "pxr/base/arch/hints.h"
421
422
423#include <typeinfo>
424#include <type_traits>
425#include <cstddef>
426
427PXR_NAMESPACE_OPEN_SCOPE
428
429// Tf_SupportsUniqueChanged is a metafunction that may be specialized to return
430// false for classes (and all derived classes) that *cannot* ever invoke unique
431// changed listeners.
432template <class T>
433struct Tf_SupportsUniqueChanged {
434 static const bool Value = true;
435};
436
437// Remnants are never able to support weak changed listeners.
438class Tf_Remnant;
439template <>
440struct Tf_SupportsUniqueChanged<Tf_Remnant> {
441 static const bool Value = false;
442};
443
444class TfWeakBase;
445
446template <class T> class TfWeakPtr;
447template <template <class> class X, class Y>
448class TfWeakPtrFacade;
449
450// Functions used for tracking. Do not implement these.
451inline void Tf_RefPtrTracker_FirstRef(const void*, const void*) { }
452inline void Tf_RefPtrTracker_LastRef(const void*, const void*) { }
453inline void Tf_RefPtrTracker_New(const void*, const void*) { }
454inline void Tf_RefPtrTracker_Delete(const void*, const void*) { }
455inline void Tf_RefPtrTracker_Assign(const void*, const void*, const void*) { }
456
457// This code is used to increment and decrement ref counts in the common case.
458// It may lock and invoke the unique changed listener, if the reference count
459// becomes unique or non-unique.
460struct Tf_RefPtr_UniqueChangedCounter {
461 static inline void
462 AddRef(TfRefBase const *refBase) {
463 if (ARCH_UNLIKELY(!refBase)) {
464 return;
465 }
466 const auto relaxed = std::memory_order_relaxed;
467 // Read the current count value.
468 std::atomic_int &counter = refBase->_GetRefCount();
469 int prevCount = counter.load(relaxed);
470 if (ARCH_UNLIKELY(prevCount < 0)) {
471 // We need to invoke the unique changed listener if count goes from
472 // -1 -> -2. Try to CAS the value to one more count if it looks
473 // like we won't take it from -1 -> -2. If that works, we're done.
474 // If not, we'll call an out-of-line function that handles the
475 // locking part.
476 if (prevCount != -1 && counter.
477 compare_exchange_weak(prevCount, prevCount-1, relaxed)) {
478 return;
479 }
480 _AddRefMaybeLocked(refBase, prevCount);
481 }
482 else {
483 // Just bump the count.
484 counter.fetch_add(1, relaxed);
485 }
486 }
487
488 static inline bool
489 RemoveRef(TfRefBase const* refBase) {
490 if (ARCH_UNLIKELY(!refBase)) {
491 return false;
492 }
493 const auto relaxed = std::memory_order_relaxed;
494 const auto release = std::memory_order_release;
495 // Read the current count value.
496 std::atomic_int &counter = refBase->_GetRefCount();
497 int prevCount = counter.load(relaxed);
498 if (ARCH_UNLIKELY(prevCount < 0)) {
499 // We need to invoke the unique changed listener if count goes from
500 // -2 -> -1. Try to CAS the value to one less count if it looks
501 // like we won't take it from -2 -> -1. If that works, we're done.
502 // If not, we'll call an out-of-line function that handles the
503 // locking part.
504 if (prevCount != -2 && counter.
505 compare_exchange_weak(prevCount, prevCount+1, release)) {
506 return prevCount == -1;
507 }
508 return _RemoveRefMaybeLocked(refBase, prevCount);
509 }
510 else {
511 // Just drop the count.
512 return counter.fetch_sub(1, release) == 1;
513 }
514 }
515
516 // Increment ptr's count if it is not zero. Return true if done so
517 // successfully, false if its count is zero.
518 TF_API static bool
519 AddRefIfNonzero(TfRefBase const *refBase);
520
521 TF_API static void
522 _AddRefMaybeLocked(TfRefBase const *refBase, int prevCount);
523
524 TF_API static bool
525 _RemoveRefMaybeLocked(TfRefBase const *refBase, int prevCount);
526
527};
528
529// This code is used to increment and decrement ref counts in the case where
530// the object pointed to explicitly does not support unique changed listeners.
531struct Tf_RefPtr_Counter {
532 static inline void
533 AddRef(TfRefBase const *refBase) {
534 if (ARCH_UNLIKELY(!refBase)) {
535 return;
536 }
537 refBase->_GetRefCount().fetch_add(1, std::memory_order_relaxed);
538 }
539
540 static inline bool
541 RemoveRef(TfRefBase const *refBase) {
542 if (ARCH_UNLIKELY(!refBase)) {
543 return false;
544 }
545 return refBase->_GetRefCount()
546 .fetch_sub(1, std::memory_order_release) == 1;
547 }
548
549 // Increment ptr's count if it is not zero. Return true if done so
550 // successfully, false if its count is zero.
551 static inline bool
552 AddRefIfNonzero(TfRefBase const *refBase) {
553 if (ARCH_UNLIKELY(!refBase)) {
554 return false;
555 }
556 auto &counter = refBase->_GetRefCount();
557 int prevCount = counter.load(std::memory_order_relaxed);
558 while (prevCount) {
559 if (counter.compare_exchange_weak(prevCount, prevCount+1)) {
560 return true;
561 }
562 }
563 return false;
564 }
565};
566
567// Helper to post a fatal error when a NULL Tf pointer is dereferenced.
568[[noreturn]]
569TF_API void
570Tf_PostNullSmartPtrDereferenceFatalError(const TfCallContext &, const char *);
571
583template <class T>
584class TfRefPtr {
585 // Select the counter based on whether T supports unique changed listeners.
586 using _Counter = typename std::conditional<
587 Tf_SupportsUniqueChanged<T>::Value &&
588 !std::is_convertible<T*, TfSimpleRefBase*>::value,
589 Tf_RefPtr_UniqueChangedCounter,
590 Tf_RefPtr_Counter>::type;
591
592public:
594 typedef T DataType;
595
596
597 template <class U> struct Rebind {
598 typedef TfRefPtr<U> Type;
599 };
600
606 TfRefPtr() : _refBase(nullptr) {
607 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
608 }
609
616 TfRefPtr(TfRefPtr<T>&& p) : _refBase(p._refBase) {
617 p._refBase = nullptr;
618 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
619 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
620 _GetObjectForTracking());
621 }
622
626 TfRefPtr(const TfRefPtr<T>& p) : _refBase(p._refBase) {
627 _AddRef();
628 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
629 }
630
634 template <template <class> class X, class U>
635 inline TfRefPtr(const TfWeakPtrFacade<X, U>& p,
636 typename std::enable_if<
637 std::is_convertible<U*, T*>::value
638 >::type * = 0);
639
672#if defined(doxygen)
673 friend inline TfRefPtr TfCreateRefPtr(T*);
674#else
675 template <class U>
676 friend inline TfRefPtr<U> TfCreateRefPtr(U*);
677#endif
678
685 template <class U>
686 explicit TfRefPtr(
687 U* ptr, typename std::enable_if<
688 std::is_convertible<U*, T*>::value>::type * = nullptr) :
689 _refBase(ptr)
690 {
691 _AddRef();
692 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
693 }
694
696 TfRefPtr(TfNullPtrType) : _refBase(nullptr)
697 {
698 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
699 }
700
702 TfRefPtr(std::nullptr_t) : _refBase(nullptr)
703 {
704 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
705 }
706
726 //
727 // It is quite possible for
728 // ptr = TfNullPtr;
729 // to delete the space that ptr actually lives in (this happens
730 // when you use a circular reference to keep an object alive).
731 // To avoid a crash, we have to ensure that deletion of the object
732 // is the last thing done in the assignment; so we use some
733 // local variables to help us out.
734 //
735
736 Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
737 _GetObjectForTracking());
738
739 const TfRefBase* tmp = _refBase;
740 _refBase = p._refBase;
741
742 p._AddRef(); // first!
743 _RemoveRef(tmp); // second!
744 return *this;
745 }
746
754 // See comment in assignment operator.
755 Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
756 _GetObjectForTracking());
757 Tf_RefPtrTracker_Assign(&p, nullptr,
758 p._GetObjectForTracking());
759
760 const TfRefBase* tmp = _refBase;
761 _refBase = p._refBase;
762 p._refBase = nullptr;
763
764 _RemoveRef(tmp);
765 return *this;
766 }
767
773 Tf_RefPtrTracker_Delete(this, _GetObjectForTracking());
774 _RemoveRef(_refBase);
775 }
776
785#if !defined(doxygen)
786 template <class U>
787#endif
788 TfRefPtr(const TfRefPtr<U>& p) : _refBase(p._refBase) {
789 static_assert(std::is_convertible<U*, T*>::value, "");
790 _AddRef();
791 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
792 }
793
804#if !defined(doxygen)
805 template <class U>
806#endif
807 TfRefPtr(TfRefPtr<U>&& p) : _refBase(p._refBase) {
808 static_assert(std::is_convertible<U*, T*>::value, "");
809 p._refBase = nullptr;
810 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
811 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
812 _GetObjectForTracking());
813 }
814
825#if !defined(doxygen)
826 template <class U>
827#endif
829 static_assert(std::is_convertible<U*, T*>::value, "");
830
831 Tf_RefPtrTracker_Assign(this,
832 reinterpret_cast<T*>(p._GetObjectForTracking()),
833 _GetObjectForTracking());
834 const TfRefBase* tmp = _refBase;
835 _refBase = p._GetData();
836 p._AddRef(); // first!
837 _RemoveRef(tmp); // second!
838 return *this;
839 }
840
852#if !defined(doxygen)
853 template <class U>
854#endif
856 static_assert(std::is_convertible<U*, T*>::value, "");
857
858 Tf_RefPtrTracker_Assign(this,
859 reinterpret_cast<T*>(p._GetObjectForTracking()),
860 _GetObjectForTracking());
861 Tf_RefPtrTracker_Assign(&p,
862 nullptr,
863 reinterpret_cast<T*>(p._GetObjectForTracking()));
864 const TfRefBase* tmp = _refBase;
865 _refBase = p._GetData();
866 p._refBase = nullptr;
867 _RemoveRef(tmp);
868 return *this;
869 }
870
875#if !defined(doxygen)
876 template <class U>
877#endif
878 auto operator==(const TfRefPtr<U>& p) const
879 -> decltype(std::declval<T *>() == std::declval<U *>(), bool()) {
880 return _refBase == p._refBase;
881 }
882
886#if !defined(doxygen)
887 template <class U>
888#endif
889 auto operator!=(const TfRefPtr<U>& p) const
890 -> decltype(std::declval<T *>() != std::declval<U *>(), bool()) {
891 return _refBase != p._refBase;
892 }
893
898#if !defined(doxygen)
899 template <class U>
900#endif
901 auto operator<(const TfRefPtr<U>& p) const
902 -> decltype(std::declval<T *>() < std::declval<U *>(), bool()) {
903 return _refBase < p._refBase;
904 }
905
906#if !defined(doxygen)
907 template <class U>
908#endif
909 auto operator>(const TfRefPtr<U>& p) const
910 -> decltype(std::declval<T *>() > std::declval<U *>(), bool()) {
911 return _refBase > p._refBase;
912 }
913
914#if !defined(doxygen)
915 template <class U>
916#endif
917 auto operator<=(const TfRefPtr<U>& p) const
918 -> decltype(std::declval<T *>() <= std::declval<U *>(), bool()) {
919 return _refBase <= p._refBase;
920 }
921
922#if !defined(doxygen)
923 template <class U>
924#endif
925 auto operator>=(const TfRefPtr<U>& p) const
926 -> decltype(std::declval<T *>() >= std::declval<U *>(), bool()) {
927 return _refBase >= p._refBase;
928 }
929
931 T* operator->() const {
932 if (_refBase) {
933 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
934 }
935 Tf_PostNullSmartPtrDereferenceFatalError(
936 TF_CALL_CONTEXT, typeid(TfRefPtr).name());
937 }
938
940 T& operator *() const {
941 return *operator->();
942 }
943
944#if !defined(doxygen)
945 using UnspecifiedBoolType = const TfRefBase * (TfRefPtr::*);
946#endif
947
949 operator UnspecifiedBoolType() const {
950 return _refBase ? &TfRefPtr::_refBase : nullptr;
951 }
952
954 bool operator !() const {
955 return _refBase == nullptr;
956 }
957
962 void swap(TfRefPtr &other) {
963 Tf_RefPtrTracker_Assign(this, other._GetObjectForTracking(),
964 _GetObjectForTracking());
965 Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
966 other._GetObjectForTracking());
967 std::swap(_refBase, other._refBase);
968 }
969
972 void Reset() {
973 *this = TfNullPtr;
974 }
975
976private:
977 const TfRefBase* _refBase;
978
979 template <class HashState, class U>
980 friend inline void TfHashAppend(HashState &, const TfRefPtr<U>&);
981 template <class U>
982 friend inline size_t hash_value(const TfRefPtr<U>&);
983
984 friend T *get_pointer(TfRefPtr const &p) {
985 return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
986 }
987
988 // Used to distinguish construction in TfCreateRefPtr.
989 class _CreateRefPtr { };
990
991 // private constructor, used by TfCreateRefPtr()
992 TfRefPtr(T* ptr, _CreateRefPtr /* unused */)
993 : _refBase(ptr)
994 {
995 /* reference count is NOT bumped */
996 Tf_RefPtrTracker_FirstRef(this, _GetObjectForTracking());
997 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
998 }
999
1000 // Hide confusing internals of actual C++ definition (e.g. DataType)
1001 // for doxygen output:
1002
1018#if defined(doxygen)
1019 // Sanitized for documentation:
1020 template <class D>
1022#else
1023 template <class D, class B>
1026
1027 template <class D, class B>
1030#endif
1031
1048#if defined(doxygen)
1049 // Sanitized for documentation:
1050 template <class D>
1052#else
1053 template <class D, class B>
1055 TfStatic_cast(const TfRefPtr<B>&);
1056
1057#endif
1058
1070#if defined(doxygen)
1071 // Sanitized for documentation:
1072 template <class D>
1074#else
1075 template <class D>
1078#endif
1079
1080 T* _GetData() const {
1081 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1082 }
1083
1084 // This method is only used when calling the hook functions for
1085 // tracking. We reinterpret_cast instead of static_cast so that
1086 // we don't need the definition of T. However, if TfRefBase is
1087 // not the first base class of T then the resulting pointer may
1088 // not point to a T. Nevertheless, it should be consistent to
1089 // all calls to the tracking functions.
1090 T* _GetObjectForTracking() const {
1091 return reinterpret_cast<T*>(const_cast<TfRefBase*>(_refBase));
1092 }
1093
1100
1101 template <class U>
1102 friend const std::type_info& TfTypeid(const TfRefPtr<U>& ptr);
1103
1104 void _AddRef() const {
1105 _Counter::AddRef(_refBase);
1106 }
1107
1108 void _RemoveRef(const TfRefBase* ptr) const {
1109 if (_Counter::RemoveRef(ptr)) {
1110 Tf_RefPtrTracker_LastRef(this,
1111 reinterpret_cast<T*>(const_cast<TfRefBase*>(ptr)));
1112 delete ptr;
1113 }
1114 }
1115
1116#if ! defined(doxygen)
1117 // doxygen is very confused by this. It declares all TfRefPtrs
1118 // to be friends.
1119 template <class U> friend class TfRefPtr;
1120 template <class U> friend class TfWeakPtr;
1121 friend class Tf_Remnant;
1122
1123 template <class U>
1125#endif
1126 friend class TfWeakBase;
1127};
1128
1129#if !defined(doxygen)
1130
1131//
1132// nullptr comparisons
1133//
1134// These are provided to avoid ambiguous overloads due to
1135// TfWeakPtrFacade::Derived comparisons with TfRefPtr.
1136//
1137
1138template <class T>
1139inline bool operator== (const TfRefPtr<T> &p, std::nullptr_t)
1140{
1141 return !p;
1142}
1143template <class T>
1144inline bool operator== (std::nullptr_t, const TfRefPtr<T> &p)
1145{
1146 return !p;
1147}
1148
1149template <class T>
1150inline bool operator!= (const TfRefPtr<T> &p, std::nullptr_t)
1151{
1152 return !(p == nullptr);
1153}
1154template <class T>
1155inline bool operator!= (std::nullptr_t, const TfRefPtr<T> &p)
1156{
1157 return !(nullptr == p);
1158}
1159
1160template <class T>
1161inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1162{
1163 return std::less<const TfRefBase *>()(get_pointer(p), nullptr);
1164}
1165template <class T>
1166inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1167{
1168 return std::less<const TfRefBase *>()(nullptr, get_pointer(p));
1169}
1170
1171template <class T>
1172inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1173{
1174 return !(nullptr < p);
1175}
1176template <class T>
1177inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1178{
1179 return !(p < nullptr);
1180}
1181
1182template <class T>
1183inline bool operator> (const TfRefPtr<T> &p, std::nullptr_t)
1184{
1185 return nullptr < p;
1186}
1187template <class T>
1188inline bool operator> (std::nullptr_t, const TfRefPtr<T> &p)
1189{
1190 return p < nullptr;
1191}
1192
1193template <class T>
1194inline bool operator>= (const TfRefPtr<T> &p, std::nullptr_t)
1195{
1196 return !(p < nullptr);
1197}
1198template <class T>
1199inline bool operator>= (std::nullptr_t, const TfRefPtr<T> &p)
1200{
1201 return !(nullptr < p);
1202}
1203
1204
1205template <typename T>
1206inline TfRefPtr<T> TfCreateRefPtr(T* ptr) {
1207 return TfRefPtr<T>(ptr, typename TfRefPtr<T>::_CreateRefPtr());
1208}
1209
1210template <class T>
1211const std::type_info&
1212TfTypeid(const TfRefPtr<T>& ptr)
1213{
1214 if (ARCH_UNLIKELY(!ptr._refBase))
1215 TF_FATAL_ERROR("called TfTypeid on NULL TfRefPtr");
1216
1217 return typeid(*ptr._GetData());
1218}
1219
1220template <class D, class T>
1221inline
1223TfDynamic_cast(const TfRefPtr<T>& ptr)
1224{
1225 typedef TfRefPtr<typename D::DataType> RefPtr;
1226 return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1227}
1228
1229template <class D, class T>
1230inline
1233{
1234 typedef TfRefPtr<typename D::DataType> RefPtr;
1235 return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1236}
1237
1238template <class D, class T>
1239inline
1241TfStatic_cast(const TfRefPtr<T>& ptr)
1242{
1243 typedef TfRefPtr<typename D::DataType> RefPtr;
1244 return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1245}
1246
1247template <class T>
1248inline
1250TfConst_cast(const TfRefPtr<const typename T::DataType>& ptr)
1251{
1252 // this ugly cast allows TfConst_cast to work without requiring
1253 // a definition for T.
1254 typedef TfRefPtr<typename T::DataType> NonConstRefPtr;
1255 return *((NonConstRefPtr*)(&ptr));
1256}
1257
1258// Specialization: prevent construction of a TfRefPtr<TfRefBase>.
1259
1260template <>
1261class TfRefPtr<TfRefBase> {
1262private:
1263 TfRefPtr() = delete;
1264};
1265
1266template <>
1267class TfRefPtr<const TfRefBase> {
1268private:
1269 TfRefPtr() = delete;
1270};
1271
1272template <class T>
1273struct TfTypeFunctions<TfRefPtr<T> > {
1274 static T* GetRawPtr(const TfRefPtr<T>& t) {
1275 return t.operator-> ();
1276 }
1277
1278 static TfRefPtr<T> ConstructFromRawPtr(T* ptr) {
1279 return TfRefPtr<T>(ptr);
1280 }
1281
1282 static bool IsNull(const TfRefPtr<T>& t) {
1283 return !t;
1284 }
1285
1286 static void Class_Object_MUST_Be_Passed_By_Address() { }
1287 static void Class_Object_MUST_Not_Be_Const() { }
1288};
1289
1290template <class T>
1291struct TfTypeFunctions<TfRefPtr<const T> > {
1292 static const T* GetRawPtr(const TfRefPtr<const T>& t) {
1293 return t.operator-> ();
1294 }
1295
1296 static TfRefPtr<const T> ConstructFromRawPtr(T* ptr) {
1297 return TfRefPtr<const T>(ptr);
1298 }
1299
1300 static bool IsNull(const TfRefPtr<const T>& t) {
1301 return !t;
1302 }
1303
1304 static void Class_Object_MUST_Be_Passed_By_Address() { }
1305};
1306
1307#endif
1308
1309#if !defined(doxygen)
1310
1311template <class T>
1312inline void
1313swap(TfRefPtr<T>& lhs, TfRefPtr<T>& rhs)
1314{
1315 lhs.swap(rhs);
1316}
1317
1318PXR_NAMESPACE_CLOSE_SCOPE
1319
1320namespace boost {
1321
1322template<typename T>
1323T *
1324get_pointer(PXR_NS::TfRefPtr<T> const& p)
1325{
1326 return get_pointer(p);
1327}
1328
1329} // end namespace boost
1330
1331PXR_NAMESPACE_OPEN_SCOPE
1332
1333// Extend boost::hash to support TfRefPtr.
1334template <class T>
1335inline size_t
1336hash_value(const TfRefPtr<T>& ptr)
1337{
1338 return TfHash()(ptr);
1339}
1340
1341template <class HashState, class T>
1342inline void
1343TfHashAppend(HashState &h, const TfRefPtr<T> &ptr)
1344{
1345 h.Append(get_pointer(ptr));
1346}
1347
1348#endif // !doxygen
1349
1350#define TF_SUPPORTS_REFPTR(T) std::is_base_of_v<TfRefBase, T>
1351
1352PXR_NAMESPACE_CLOSE_SCOPE
1353
1354#endif // PXR_BASE_TF_REF_PTR_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:460
Enable a concrete base class for use with TfRefPtr.
Definition: refBase.h:56
Reference-counted smart pointer utility class.
Definition: refPtr.h:584
TfRefPtr< T > & operator=(const TfRefPtr< T > &p)
Assigns pointer to point at p's object, and increments reference count.
Definition: refPtr.h:725
T & operator*() const
Dereferences the stored pointer.
Definition: refPtr.h:940
TfRefPtr< T > & operator=(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
Definition: refPtr.h:753
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).
Definition: refPtr.h:878
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.
Definition: refPtr.h:828
void Reset()
Set this pointer to point to no object.
Definition: refPtr.h:972
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
Definition: refPtr.h:616
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.
Definition: refPtr.h:772
bool operator!() const
True if the pointer points to NULL.
Definition: refPtr.h:954
void swap(TfRefPtr &other)
Swap this pointer with other.
Definition: refPtr.h:962
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
Definition: refPtr.h:686
T * operator->() const
Accessor to T's public members.
Definition: refPtr.h:931
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.
Definition: refPtr.h:696
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
Definition: refPtr.h:626
TfRefPtr< T > & operator=(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
Definition: refPtr.h:855
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.
Definition: refPtr.h:889
friend TfRefPtr< D > TfDynamic_cast(const TfRefPtr< T > &)
Allows dynamic casting of a TfRefPtr.
TfRefPtr()
Initialize pointer to nullptr.
Definition: refPtr.h:606
TfRefPtr(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
Definition: refPtr.h:807
TfRefPtr(const TfRefPtr< U > &p)
Initializes to point at p's object, and increments reference count.
Definition: refPtr.h:788
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...
Definition: refPtr.h:901
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
Definition: refPtr.h:702
T DataType
Convenience type accessor to underlying type T for template code.
Definition: refPtr.h:594
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124
Pointer storage with deletion detection.
Definition: weakPtr.h:128
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.
Definition: diagnostic.h:91
Compiler hints.
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.
Definition: typeFunctions.h:37
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
Definition: token.h:437
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:260