Loading...
Searching...
No Matches
refPtr.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef PXR_BASE_TF_REF_PTR_H
25#define PXR_BASE_TF_REF_PTR_H
26
426
427#include "pxr/pxr.h"
428
430#include "pxr/base/tf/hash.h"
431#include "pxr/base/tf/nullPtr.h"
432#include "pxr/base/tf/refBase.h"
435#include "pxr/base/tf/api.h"
436
437#include "pxr/base/arch/hints.h"
438
439
440#include <typeinfo>
441#include <type_traits>
442#include <cstddef>
443
444PXR_NAMESPACE_OPEN_SCOPE
445
446// Tf_SupportsUniqueChanged is a metafunction that may be specialized to return
447// false for classes (and all derived classes) that *cannot* ever invoke unique
448// changed listeners.
449template <class T>
450struct Tf_SupportsUniqueChanged {
451 static const bool Value = true;
452};
453
454// Remnants are never able to support weak changed listeners.
455class Tf_Remnant;
456template <>
457struct Tf_SupportsUniqueChanged<Tf_Remnant> {
458 static const bool Value = false;
459};
460
461class TfWeakBase;
462
463template <class T> class TfWeakPtr;
464template <template <class> class X, class Y>
465class TfWeakPtrFacade;
466
467// Functions used for tracking. Do not implement these.
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*) { }
473
474// This code is used to increment and decrement ref counts in the common case.
475// It may lock and invoke the unique changed listener, if the reference count
476// becomes unique or non-unique.
477struct Tf_RefPtr_UniqueChangedCounter {
478 static inline void
479 AddRef(TfRefBase const *refBase) {
480 if (ARCH_UNLIKELY(!refBase)) {
481 return;
482 }
483 const auto relaxed = std::memory_order_relaxed;
484 // Read the current count value.
485 std::atomic_int &counter = refBase->_GetRefCount();
486 int prevCount = counter.load(relaxed);
487 if (ARCH_UNLIKELY(prevCount < 0)) {
488 // We need to invoke the unique changed listener if count goes from
489 // -1 -> -2. Try to CAS the value to one more count if it looks
490 // like we won't take it from -1 -> -2. If that works, we're done.
491 // If not, we'll call an out-of-line function that handles the
492 // locking part.
493 if (prevCount != -1 && counter.
494 compare_exchange_weak(prevCount, prevCount-1, relaxed)) {
495 return;
496 }
497 _AddRefMaybeLocked(refBase, prevCount);
498 }
499 else {
500 // Just bump the count.
501 counter.fetch_add(1, relaxed);
502 }
503 }
504
505 static inline bool
506 RemoveRef(TfRefBase const* refBase) {
507 if (ARCH_UNLIKELY(!refBase)) {
508 return false;
509 }
510 const auto relaxed = std::memory_order_relaxed;
511 const auto release = std::memory_order_release;
512 // Read the current count value.
513 std::atomic_int &counter = refBase->_GetRefCount();
514 int prevCount = counter.load(relaxed);
515 if (ARCH_UNLIKELY(prevCount < 0)) {
516 // We need to invoke the unique changed listener if count goes from
517 // -2 -> -1. Try to CAS the value to one less count if it looks
518 // like we won't take it from -2 -> -1. If that works, we're done.
519 // If not, we'll call an out-of-line function that handles the
520 // locking part.
521 if (prevCount != -2 && counter.
522 compare_exchange_weak(prevCount, prevCount+1, release)) {
523 return prevCount == -1;
524 }
525 return _RemoveRefMaybeLocked(refBase, prevCount);
526 }
527 else {
528 // Just drop the count.
529 return counter.fetch_sub(1, release) == 1;
530 }
531 }
532
533 // Increment ptr's count if it is not zero. Return true if done so
534 // successfully, false if its count is zero.
535 TF_API static bool
536 AddRefIfNonzero(TfRefBase const *refBase);
537
538 TF_API static void
539 _AddRefMaybeLocked(TfRefBase const *refBase, int prevCount);
540
541 TF_API static bool
542 _RemoveRefMaybeLocked(TfRefBase const *refBase, int prevCount);
543
544};
545
546// This code is used to increment and decrement ref counts in the case where
547// the object pointed to explicitly does not support unique changed listeners.
548struct Tf_RefPtr_Counter {
549 static inline void
550 AddRef(TfRefBase const *refBase) {
551 if (ARCH_UNLIKELY(!refBase)) {
552 return;
553 }
554 refBase->_GetRefCount().fetch_add(1, std::memory_order_relaxed);
555 }
556
557 static inline bool
558 RemoveRef(TfRefBase const *refBase) {
559 if (ARCH_UNLIKELY(!refBase)) {
560 return false;
561 }
562 return refBase->_GetRefCount()
563 .fetch_sub(1, std::memory_order_release) == 1;
564 }
565
566 // Increment ptr's count if it is not zero. Return true if done so
567 // successfully, false if its count is zero.
568 static inline bool
569 AddRefIfNonzero(TfRefBase const *refBase) {
570 if (ARCH_UNLIKELY(!refBase)) {
571 return false;
572 }
573 auto &counter = refBase->_GetRefCount();
574 int prevCount = counter.load(std::memory_order_relaxed);
575 while (prevCount) {
576 if (counter.compare_exchange_weak(prevCount, prevCount+1)) {
577 return true;
578 }
579 }
580 return false;
581 }
582};
583
584// Helper to post a fatal error when a NULL Tf pointer is dereferenced.
585[[noreturn]]
586TF_API void
587Tf_PostNullSmartPtrDereferenceFatalError(const TfCallContext &, const char *);
588
600template <class T>
601class TfRefPtr {
602 // Select the counter based on whether T supports unique changed listeners.
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;
608
609public:
611 typedef T DataType;
612
613
614 template <class U> struct Rebind {
615 typedef TfRefPtr<U> Type;
616 };
617
623 TfRefPtr() : _refBase(nullptr) {
624 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
625 }
626
633 TfRefPtr(TfRefPtr<T>&& p) : _refBase(p._refBase) {
634 p._refBase = nullptr;
635 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
636 Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
637 _GetObjectForTracking());
638 }
639
643 TfRefPtr(const TfRefPtr<T>& p) : _refBase(p._refBase) {
644 _AddRef();
645 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
646 }
647
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
655 >::type * = 0);
656
689#if defined(doxygen)
690 friend inline TfRefPtr TfCreateRefPtr(T*);
691#else
692 template <class U>
693 friend inline TfRefPtr<U> TfCreateRefPtr(U*);
694#endif
695
702 template <class U>
703 explicit TfRefPtr(
704 U* ptr, typename std::enable_if<
705 std::is_convertible<U*, T*>::value>::type * = nullptr) :
706 _refBase(ptr)
707 {
708 _AddRef();
709 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
710 }
711
713 TfRefPtr(TfNullPtrType) : _refBase(nullptr)
714 {
715 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
716 }
717
719 TfRefPtr(std::nullptr_t) : _refBase(nullptr)
720 {
721 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
722 }
723
743 //
744 // It is quite possible for
745 // ptr = TfNullPtr;
746 // to delete the space that ptr actually lives in (this happens
747 // when you use a circular reference to keep an object alive).
748 // To avoid a crash, we have to ensure that deletion of the object
749 // is the last thing done in the assignment; so we use some
750 // local variables to help us out.
751 //
752
753 Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
754 _GetObjectForTracking());
755
756 const TfRefBase* tmp = _refBase;
757 _refBase = p._refBase;
758
759 p._AddRef(); // first!
760 _RemoveRef(tmp); // second!
761 return *this;
762 }
763
771 // See comment in assignment operator.
772 Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
773 _GetObjectForTracking());
774 Tf_RefPtrTracker_Assign(&p, nullptr,
775 p._GetObjectForTracking());
776
777 const TfRefBase* tmp = _refBase;
778 _refBase = p._refBase;
779 p._refBase = nullptr;
780
781 _RemoveRef(tmp);
782 return *this;
783 }
784
790 Tf_RefPtrTracker_Delete(this, _GetObjectForTracking());
791 _RemoveRef(_refBase);
792 }
793
802#if !defined(doxygen)
803 template <class U>
804#endif
805 TfRefPtr(const TfRefPtr<U>& p) : _refBase(p._refBase) {
806 static_assert(std::is_convertible<U*, T*>::value, "");
807 _AddRef();
808 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
809 }
810
821#if !defined(doxygen)
822 template <class U>
823#endif
824 TfRefPtr(TfRefPtr<U>&& p) : _refBase(p._refBase) {
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());
830 }
831
842#if !defined(doxygen)
843 template <class U>
844#endif
846 static_assert(std::is_convertible<U*, T*>::value, "");
847
848 Tf_RefPtrTracker_Assign(this,
849 reinterpret_cast<T*>(p._GetObjectForTracking()),
850 _GetObjectForTracking());
851 const TfRefBase* tmp = _refBase;
852 _refBase = p._GetData();
853 p._AddRef(); // first!
854 _RemoveRef(tmp); // second!
855 return *this;
856 }
857
869#if !defined(doxygen)
870 template <class U>
871#endif
873 static_assert(std::is_convertible<U*, T*>::value, "");
874
875 Tf_RefPtrTracker_Assign(this,
876 reinterpret_cast<T*>(p._GetObjectForTracking()),
877 _GetObjectForTracking());
878 Tf_RefPtrTracker_Assign(&p,
879 nullptr,
880 reinterpret_cast<T*>(p._GetObjectForTracking()));
881 const TfRefBase* tmp = _refBase;
882 _refBase = p._GetData();
883 p._refBase = nullptr;
884 _RemoveRef(tmp);
885 return *this;
886 }
887
892#if !defined(doxygen)
893 template <class U>
894#endif
895 auto operator==(const TfRefPtr<U>& p) const
896 -> decltype(std::declval<T *>() == std::declval<U *>(), bool()) {
897 return _refBase == p._refBase;
898 }
899
903#if !defined(doxygen)
904 template <class U>
905#endif
906 auto operator!=(const TfRefPtr<U>& p) const
907 -> decltype(std::declval<T *>() != std::declval<U *>(), bool()) {
908 return _refBase != p._refBase;
909 }
910
915#if !defined(doxygen)
916 template <class U>
917#endif
918 auto operator<(const TfRefPtr<U>& p) const
919 -> decltype(std::declval<T *>() < std::declval<U *>(), bool()) {
920 return _refBase < p._refBase;
921 }
922
923#if !defined(doxygen)
924 template <class U>
925#endif
926 auto operator>(const TfRefPtr<U>& p) const
927 -> decltype(std::declval<T *>() > std::declval<U *>(), bool()) {
928 return _refBase > p._refBase;
929 }
930
931#if !defined(doxygen)
932 template <class U>
933#endif
934 auto operator<=(const TfRefPtr<U>& p) const
935 -> decltype(std::declval<T *>() <= std::declval<U *>(), bool()) {
936 return _refBase <= p._refBase;
937 }
938
939#if !defined(doxygen)
940 template <class U>
941#endif
942 auto operator>=(const TfRefPtr<U>& p) const
943 -> decltype(std::declval<T *>() >= std::declval<U *>(), bool()) {
944 return _refBase >= p._refBase;
945 }
946
948 T* operator->() const {
949 if (_refBase) {
950 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
951 }
952 Tf_PostNullSmartPtrDereferenceFatalError(
953 TF_CALL_CONTEXT, typeid(TfRefPtr).name());
954 }
955
957 T& operator *() const {
958 return *operator->();
959 }
960
961#if !defined(doxygen)
962 using UnspecifiedBoolType = const TfRefBase * (TfRefPtr::*);
963#endif
964
966 operator UnspecifiedBoolType() const {
967 return _refBase ? &TfRefPtr::_refBase : nullptr;
968 }
969
971 bool operator !() const {
972 return _refBase == nullptr;
973 }
974
979 void swap(TfRefPtr &other) {
980 Tf_RefPtrTracker_Assign(this, other._GetObjectForTracking(),
981 _GetObjectForTracking());
982 Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
983 other._GetObjectForTracking());
984 std::swap(_refBase, other._refBase);
985 }
986
989 void Reset() {
990 *this = TfNullPtr;
991 }
992
993private:
994 const TfRefBase* _refBase;
995
996 template <class HashState, class U>
997 friend inline void TfHashAppend(HashState &, const TfRefPtr<U>&);
998 template <class U>
999 friend inline size_t hash_value(const TfRefPtr<U>&);
1000
1001 friend T *get_pointer(TfRefPtr const &p) {
1002 return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
1003 }
1004
1005 // Used to distinguish construction in TfCreateRefPtr.
1006 class _CreateRefPtr { };
1007
1008 // private constructor, used by TfCreateRefPtr()
1009 TfRefPtr(T* ptr, _CreateRefPtr /* unused */)
1010 : _refBase(ptr)
1011 {
1012 /* reference count is NOT bumped */
1013 Tf_RefPtrTracker_FirstRef(this, _GetObjectForTracking());
1014 Tf_RefPtrTracker_New(this, _GetObjectForTracking());
1015 }
1016
1017 // Hide confusing internals of actual C++ definition (e.g. DataType)
1018 // for doxygen output:
1019
1035#if defined(doxygen)
1036 // Sanitized for documentation:
1037 template <class D>
1039#else
1040 template <class D, class B>
1043
1044 template <class D, class B>
1047#endif
1048
1065#if defined(doxygen)
1066 // Sanitized for documentation:
1067 template <class D>
1069#else
1070 template <class D, class B>
1072 TfStatic_cast(const TfRefPtr<B>&);
1073
1074#endif
1075
1087#if defined(doxygen)
1088 // Sanitized for documentation:
1089 template <class D>
1091#else
1092 template <class D>
1095#endif
1096
1097 T* _GetData() const {
1098 return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1099 }
1100
1101 // This method is only used when calling the hook functions for
1102 // tracking. We reinterpret_cast instead of static_cast so that
1103 // we don't need the definition of T. However, if TfRefBase is
1104 // not the first base class of T then the resulting pointer may
1105 // not point to a T. Nevertheless, it should be consistent to
1106 // all calls to the tracking functions.
1107 T* _GetObjectForTracking() const {
1108 return reinterpret_cast<T*>(const_cast<TfRefBase*>(_refBase));
1109 }
1110
1117
1118 template <class U>
1119 friend const std::type_info& TfTypeid(const TfRefPtr<U>& ptr);
1120
1121 void _AddRef() const {
1122 _Counter::AddRef(_refBase);
1123 }
1124
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)));
1129 delete ptr;
1130 }
1131 }
1132
1133#if ! defined(doxygen)
1134 // doxygen is very confused by this. It declares all TfRefPtrs
1135 // to be friends.
1136 template <class U> friend class TfRefPtr;
1137 template <class U> friend class TfWeakPtr;
1138 friend class Tf_Remnant;
1139
1140 template <class U>
1142#endif
1143 friend class TfWeakBase;
1144};
1145
1146#if !defined(doxygen)
1147
1148//
1149// nullptr comparisons
1150//
1151// These are provided to avoid ambiguous overloads due to
1152// TfWeakPtrFacade::Derived comparisons with TfRefPtr.
1153//
1154
1155template <class T>
1156inline bool operator== (const TfRefPtr<T> &p, std::nullptr_t)
1157{
1158 return !p;
1159}
1160template <class T>
1161inline bool operator== (std::nullptr_t, const TfRefPtr<T> &p)
1162{
1163 return !p;
1164}
1165
1166template <class T>
1167inline bool operator!= (const TfRefPtr<T> &p, std::nullptr_t)
1168{
1169 return !(p == nullptr);
1170}
1171template <class T>
1172inline bool operator!= (std::nullptr_t, const TfRefPtr<T> &p)
1173{
1174 return !(nullptr == p);
1175}
1176
1177template <class T>
1178inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1179{
1180 return std::less<const TfRefBase *>()(get_pointer(p), nullptr);
1181}
1182template <class T>
1183inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1184{
1185 return std::less<const TfRefBase *>()(nullptr, get_pointer(p));
1186}
1187
1188template <class T>
1189inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1190{
1191 return !(nullptr < p);
1192}
1193template <class T>
1194inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1195{
1196 return !(p < nullptr);
1197}
1198
1199template <class T>
1200inline bool operator> (const TfRefPtr<T> &p, std::nullptr_t)
1201{
1202 return nullptr < p;
1203}
1204template <class T>
1205inline bool operator> (std::nullptr_t, const TfRefPtr<T> &p)
1206{
1207 return p < nullptr;
1208}
1209
1210template <class T>
1211inline bool operator>= (const TfRefPtr<T> &p, std::nullptr_t)
1212{
1213 return !(p < nullptr);
1214}
1215template <class T>
1216inline bool operator>= (std::nullptr_t, const TfRefPtr<T> &p)
1217{
1218 return !(nullptr < p);
1219}
1220
1221
1222template <typename T>
1223inline TfRefPtr<T> TfCreateRefPtr(T* ptr) {
1224 return TfRefPtr<T>(ptr, typename TfRefPtr<T>::_CreateRefPtr());
1225}
1226
1227template <class T>
1228const std::type_info&
1229TfTypeid(const TfRefPtr<T>& ptr)
1230{
1231 if (ARCH_UNLIKELY(!ptr._refBase))
1232 TF_FATAL_ERROR("called TfTypeid on NULL TfRefPtr");
1233
1234 return typeid(*ptr._GetData());
1235}
1236
1237template <class D, class T>
1238inline
1240TfDynamic_cast(const TfRefPtr<T>& ptr)
1241{
1242 typedef TfRefPtr<typename D::DataType> RefPtr;
1243 return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1244}
1245
1246template <class D, class T>
1247inline
1250{
1251 typedef TfRefPtr<typename D::DataType> RefPtr;
1252 return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1253}
1254
1255template <class D, class T>
1256inline
1258TfStatic_cast(const TfRefPtr<T>& ptr)
1259{
1260 typedef TfRefPtr<typename D::DataType> RefPtr;
1261 return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1262}
1263
1264template <class T>
1265inline
1267TfConst_cast(const TfRefPtr<const typename T::DataType>& ptr)
1268{
1269 // this ugly cast allows TfConst_cast to work without requiring
1270 // a definition for T.
1271 typedef TfRefPtr<typename T::DataType> NonConstRefPtr;
1272 return *((NonConstRefPtr*)(&ptr));
1273}
1274
1275// Specialization: prevent construction of a TfRefPtr<TfRefBase>.
1276
1277template <>
1278class TfRefPtr<TfRefBase> {
1279private:
1280 TfRefPtr() = delete;
1281};
1282
1283template <>
1284class TfRefPtr<const TfRefBase> {
1285private:
1286 TfRefPtr() = delete;
1287};
1288
1289template <class T>
1290struct TfTypeFunctions<TfRefPtr<T> > {
1291 static T* GetRawPtr(const TfRefPtr<T>& t) {
1292 return t.operator-> ();
1293 }
1294
1295 static TfRefPtr<T> ConstructFromRawPtr(T* ptr) {
1296 return TfRefPtr<T>(ptr);
1297 }
1298
1299 static bool IsNull(const TfRefPtr<T>& t) {
1300 return !t;
1301 }
1302
1303 static void Class_Object_MUST_Be_Passed_By_Address() { }
1304 static void Class_Object_MUST_Not_Be_Const() { }
1305};
1306
1307template <class T>
1308struct TfTypeFunctions<TfRefPtr<const T> > {
1309 static const T* GetRawPtr(const TfRefPtr<const T>& t) {
1310 return t.operator-> ();
1311 }
1312
1313 static TfRefPtr<const T> ConstructFromRawPtr(T* ptr) {
1314 return TfRefPtr<const T>(ptr);
1315 }
1316
1317 static bool IsNull(const TfRefPtr<const T>& t) {
1318 return !t;
1319 }
1320
1321 static void Class_Object_MUST_Be_Passed_By_Address() { }
1322};
1323
1324#endif
1325
1326#if !defined(doxygen)
1327
1328template <class T>
1329inline void
1330swap(TfRefPtr<T>& lhs, TfRefPtr<T>& rhs)
1331{
1332 lhs.swap(rhs);
1333}
1334
1335PXR_NAMESPACE_CLOSE_SCOPE
1336
1337namespace boost {
1338
1339template<typename T>
1340T *
1341get_pointer(PXR_NS::TfRefPtr<T> const& p)
1342{
1343 return get_pointer(p);
1344}
1345
1346} // end namespace boost
1347
1348PXR_NAMESPACE_OPEN_SCOPE
1349
1350// Extend boost::hash to support TfRefPtr.
1351template <class T>
1352inline size_t
1353hash_value(const TfRefPtr<T>& ptr)
1354{
1355 return TfHash()(ptr);
1356}
1357
1358template <class HashState, class T>
1359inline void
1360TfHashAppend(HashState &h, const TfRefPtr<T> &ptr)
1361{
1362 h.Append(get_pointer(ptr));
1363}
1364
1365#endif // !doxygen
1366
1367#define TF_SUPPORTS_REFPTR(T) std::is_base_of_v<TfRefBase, T>
1368
1369PXR_NAMESPACE_CLOSE_SCOPE
1370
1371#endif // PXR_BASE_TF_REF_PTR_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:477
Enable a concrete base class for use with TfRefPtr.
Definition: refBase.h:73
Reference-counted smart pointer utility class.
Definition: refPtr.h:601
TfRefPtr< T > & operator=(const TfRefPtr< T > &p)
Assigns pointer to point at p's object, and increments reference count.
Definition: refPtr.h:742
T & operator*() const
Dereferences the stored pointer.
Definition: refPtr.h:957
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:770
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:895
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:845
void Reset()
Set this pointer to point to no object.
Definition: refPtr.h:989
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
Definition: refPtr.h:633
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:789
bool operator!() const
True if the pointer points to NULL.
Definition: refPtr.h:971
void swap(TfRefPtr &other)
Swap this pointer with other.
Definition: refPtr.h:979
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
Definition: refPtr.h:703
T * operator->() const
Accessor to T's public members.
Definition: refPtr.h:948
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:713
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
Definition: refPtr.h:643
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:872
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:906
friend TfRefPtr< D > TfDynamic_cast(const TfRefPtr< T > &)
Allows dynamic casting of a TfRefPtr.
TfRefPtr()
Initialize pointer to nullptr.
Definition: refPtr.h:623
TfRefPtr(TfRefPtr< U > &&p)
Moves the pointer managed by p to *this and leaves p pointing at the NULL object.
Definition: refPtr.h:824
TfRefPtr(const TfRefPtr< U > &p)
Initializes to point at p's object, and increments reference count.
Definition: refPtr.h:805
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:918
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
Definition: refPtr.h:719
T DataType
Convenience type accessor to underlying type T for template code.
Definition: refPtr.h:611
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
Pointer storage with deletion detection.
Definition: weakPtr.h:145
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:108
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:54
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.
Definition: token.h:454
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:277