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/nullPtr.h"
431 #include "pxr/base/tf/refBase.h"
434 #include "pxr/base/tf/api.h"
435 
436 #include "pxr/base/arch/hints.h"
437 
438 #include <boost/functional/hash_fwd.hpp>
439 
440 #include <typeinfo>
441 #include <type_traits>
442 #include <cstddef>
443 
444 PXR_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.
449 template <class T>
450 struct Tf_SupportsUniqueChanged {
451  static const bool Value = true;
452 };
453 
454 // Remnants are never able to support weak changed listeners.
455 class Tf_Remnant;
456 template <>
457 struct Tf_SupportsUniqueChanged<Tf_Remnant> {
458  static const bool Value = false;
459 };
460 
461 class TfWeakBase;
462 
463 template <class T> class TfWeakPtr;
464 template <template <class> class X, class Y>
465 class TfWeakPtrFacade;
466 
467 // Functions used for tracking. Do not implement these.
468 inline void Tf_RefPtrTracker_FirstRef(const void*, const void*) { }
469 inline void Tf_RefPtrTracker_LastRef(const void*, const void*) { }
470 inline void Tf_RefPtrTracker_New(const void*, const void*) { }
471 inline void Tf_RefPtrTracker_Delete(const void*, const void*) { }
472 inline 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.
477 struct Tf_RefPtr_UniqueChangedCounter {
478  static inline int
479  AddRef(TfRefBase const *refBase)
480  {
481  if (refBase) {
482  // Check to see if we need to invoke the unique changed listener.
483  if (refBase->_shouldInvokeUniqueChangedListener)
484  return _AddRef(refBase);
485  else
486  return refBase->GetRefCount()._FetchAndAdd(1);
487  }
488  return 0;
489  }
490 
491  static inline bool
492  RemoveRef(TfRefBase const* refBase) {
493  if (refBase) {
494  // Check to see if we need to invoke the unique changed listener.
495  return refBase->_shouldInvokeUniqueChangedListener ?
496  _RemoveRef(refBase) :
497  refBase->GetRefCount()._DecrementAndTestIfZero();
498  }
499  return false;
500  }
501 
502  // Increment ptr's count if it is not zero. Return true if done so
503  // successfully, false if its count is zero.
504  static inline bool
505  AddRefIfNonzero(TfRefBase const *ptr) {
506  if (!ptr)
507  return false;
508  if (ptr->_shouldInvokeUniqueChangedListener) {
509  return _AddRefIfNonzero(ptr);
510  } else {
511  auto &counter = ptr->GetRefCount()._counter;
512  auto val = counter.load();
513  do {
514  if (val == 0)
515  return false;
516  } while (!counter.compare_exchange_weak(val, val + 1));
517  return true;
518  }
519  }
520 
521  TF_API static bool _RemoveRef(TfRefBase const *refBase);
522 
523  TF_API static int _AddRef(TfRefBase const *refBase);
524 
525  TF_API static bool _AddRefIfNonzero(TfRefBase const *refBase);
526 };
527 
528 // This code is used to increment and decrement ref counts in the case where
529 // the object pointed to explicitly does not support unique changed listeners.
530 struct Tf_RefPtr_Counter {
531  static inline int
532  AddRef(TfRefBase const *refBase) {
533  if (refBase)
534  return refBase->GetRefCount()._FetchAndAdd(1);
535  return 0;
536  }
537 
538  static inline bool
539  RemoveRef(TfRefBase const *ptr) {
540  return (ptr && (ptr->GetRefCount()._DecrementAndTestIfZero()));
541  }
542 
543  // Increment ptr's count if it is not zero. Return true if done so
544  // successfully, false if its count is zero.
545  static inline bool
546  AddRefIfNonzero(TfRefBase const *ptr) {
547  if (!ptr)
548  return false;
549  auto &counter = ptr->GetRefCount()._counter;
550  auto val = counter.load();
551  do {
552  if (val == 0)
553  return false;
554  } while (!counter.compare_exchange_weak(val, val + 1));
555  return true;
556  }
557 };
558 
559 // Helper to post a fatal error when a NULL Tf pointer is dereferenced.
560 [[noreturn]]
561 TF_API void
562 Tf_PostNullSmartPtrDereferenceFatalError(const TfCallContext &, const char *);
563 
575 template <class T>
576 class TfRefPtr {
577  // Select the counter based on whether T supports unique changed listeners.
578  using _Counter = typename std::conditional<
579  Tf_SupportsUniqueChanged<T>::Value &&
580  !std::is_convertible<T*, TfSimpleRefBase*>::value,
581  Tf_RefPtr_UniqueChangedCounter,
582  Tf_RefPtr_Counter>::type;
583 
584 public:
586  typedef T DataType;
587 
588 
589  template <class U> struct Rebind {
590  typedef TfRefPtr<U> Type;
591  };
592 
598  TfRefPtr() : _refBase(nullptr) {
599  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
600  }
601 
608  TfRefPtr(TfRefPtr<T>&& p) : _refBase(p._refBase) {
609  p._refBase = nullptr;
610  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
611  Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
612  _GetObjectForTracking());
613  }
614 
618  TfRefPtr(const TfRefPtr<T>& p) : _refBase(p._refBase) {
619  _AddRef();
620  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
621  }
622 
626  template <template <class> class X, class U>
627  inline TfRefPtr(const TfWeakPtrFacade<X, U>& p,
628  typename std::enable_if<
629  std::is_convertible<U*, T*>::value
630  >::type * = 0);
631 
664 #if defined(doxygen)
665  friend inline TfRefPtr TfCreateRefPtr(T*);
666 #else
667  template <class U>
668  friend inline TfRefPtr<U> TfCreateRefPtr(U*);
669 #endif
670 
677  template <class U>
678  explicit TfRefPtr(
679  U* ptr, typename std::enable_if<
680  std::is_convertible<U*, T*>::value>::type * = nullptr) :
681  _refBase(ptr)
682  {
683  _AddRef();
684  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
685  }
686 
688  TfRefPtr(TfNullPtrType) : _refBase(nullptr)
689  {
690  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
691  }
692 
694  TfRefPtr(std::nullptr_t) : _refBase(nullptr)
695  {
696  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
697  }
698 
718  //
719  // It is quite possible for
720  // ptr = TfNullPtr;
721  // to delete the space that ptr actually lives in (this happens
722  // when you use a circular reference to keep an object alive).
723  // To avoid a crash, we have to ensure that deletion of the object
724  // is the last thing done in the assignment; so we use some
725  // local variables to help us out.
726  //
727 
728  Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
729  _GetObjectForTracking());
730 
731  const TfRefBase* tmp = _refBase;
732  _refBase = p._refBase;
733 
734  p._AddRef(); // first!
735  _RemoveRef(tmp); // second!
736  return *this;
737  }
738 
746  // See comment in assignment operator.
747  Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
748  _GetObjectForTracking());
749  Tf_RefPtrTracker_Assign(&p, nullptr,
750  p._GetObjectForTracking());
751 
752  const TfRefBase* tmp = _refBase;
753  _refBase = p._refBase;
754  p._refBase = nullptr;
755 
756  _RemoveRef(tmp);
757  return *this;
758  }
759 
765  Tf_RefPtrTracker_Delete(this, _GetObjectForTracking());
766  _RemoveRef(_refBase);
767  }
768 
777 #if !defined(doxygen)
778  template <class U>
779 #endif
780  TfRefPtr(const TfRefPtr<U>& p) : _refBase(p._refBase) {
781  static_assert(std::is_convertible<U*, T*>::value, "");
782  _AddRef();
783  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
784  }
785 
796 #if !defined(doxygen)
797  template <class U>
798 #endif
799  TfRefPtr(TfRefPtr<U>&& p) : _refBase(p._refBase) {
800  static_assert(std::is_convertible<U*, T*>::value, "");
801  p._refBase = nullptr;
802  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
803  Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
804  _GetObjectForTracking());
805  }
806 
817 #if !defined(doxygen)
818  template <class U>
819 #endif
821  static_assert(std::is_convertible<U*, T*>::value, "");
822 
823  Tf_RefPtrTracker_Assign(this,
824  reinterpret_cast<T*>(p._GetObjectForTracking()),
825  _GetObjectForTracking());
826  const TfRefBase* tmp = _refBase;
827  _refBase = p._GetData();
828  p._AddRef(); // first!
829  _RemoveRef(tmp); // second!
830  return *this;
831  }
832 
844 #if !defined(doxygen)
845  template <class U>
846 #endif
848  static_assert(std::is_convertible<U*, T*>::value, "");
849 
850  Tf_RefPtrTracker_Assign(this,
851  reinterpret_cast<T*>(p._GetObjectForTracking()),
852  _GetObjectForTracking());
853  Tf_RefPtrTracker_Assign(&p,
854  nullptr,
855  reinterpret_cast<T*>(p._GetObjectForTracking()));
856  const TfRefBase* tmp = _refBase;
857  _refBase = p._GetData();
858  p._refBase = nullptr;
859  _RemoveRef(tmp);
860  return *this;
861  }
862 
867 #if !defined(doxygen)
868  template <class U>
869 #endif
870  auto operator==(const TfRefPtr<U>& p) const
871  -> decltype(std::declval<T *>() == std::declval<U *>(), bool()) {
872  return _refBase == p._refBase;
873  }
874 
878 #if !defined(doxygen)
879  template <class U>
880 #endif
881  auto operator!=(const TfRefPtr<U>& p) const
882  -> decltype(std::declval<T *>() != std::declval<U *>(), bool()) {
883  return _refBase != p._refBase;
884  }
885 
890 #if !defined(doxygen)
891  template <class U>
892 #endif
893  auto operator<(const TfRefPtr<U>& p) const
894  -> decltype(std::declval<T *>() < std::declval<U *>(), bool()) {
895  return _refBase < p._refBase;
896  }
897 
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 
923  T* operator->() const {
924  if (_refBase) {
925  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
926  }
927  Tf_PostNullSmartPtrDereferenceFatalError(
928  TF_CALL_CONTEXT, typeid(TfRefPtr).name());
929  }
930 
932  T& operator *() const {
933  return *operator->();
934  }
935 
936 #if !defined(doxygen)
937  using UnspecifiedBoolType = const TfRefBase * (TfRefPtr::*);
938 #endif
939 
941  operator UnspecifiedBoolType() const {
942  return _refBase ? &TfRefPtr::_refBase : nullptr;
943  }
944 
946  bool operator !() const {
947  return _refBase == nullptr;
948  }
949 
954  void swap(TfRefPtr &other) {
955  Tf_RefPtrTracker_Assign(this, other._GetObjectForTracking(),
956  _GetObjectForTracking());
957  Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
958  other._GetObjectForTracking());
959  std::swap(_refBase, other._refBase);
960  }
961 
964  void Reset() {
965  *this = TfNullPtr;
966  }
967 
968 private:
969  const TfRefBase* _refBase;
970 
971  template <class HashState, class U>
972  friend inline void TfHashAppend(HashState &, const TfRefPtr<U>&);
973  template <class U>
974  friend inline size_t hash_value(const TfRefPtr<U>&);
975 
976  friend T *get_pointer(TfRefPtr const &p) {
977  return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
978  }
979 
980  // Used to distinguish construction in TfCreateRefPtr.
981  class _CreateRefPtr { };
982 
983  // private constructor, used by TfCreateRefPtr()
984  TfRefPtr(T* ptr, _CreateRefPtr /* unused */)
985  : _refBase(ptr)
986  {
987  /* reference count is NOT bumped */
988  Tf_RefPtrTracker_FirstRef(this, _GetObjectForTracking());
989  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
990  }
991 
992  // Hide confusing internals of actual C++ definition (e.g. DataType)
993  // for doxygen output:
994 
1010 #if defined(doxygen)
1011  // Sanitized for documentation:
1012  template <class D>
1013  friend inline TfRefPtr<D> TfDynamic_cast(const TfRefPtr<T>&);
1014 #else
1015  template <class D, class B>
1017  TfDynamic_cast(const TfRefPtr<B>&);
1018 
1019  template <class D, class B>
1022 #endif
1023 
1040 #if defined(doxygen)
1041  // Sanitized for documentation:
1042  template <class D>
1043  friend inline TfRefPtr<D> TfStatic_cast(const TfRefPtr<T>&);
1044 #else
1045  template <class D, class B>
1047  TfStatic_cast(const TfRefPtr<B>&);
1048 
1049 #endif
1050 
1062 #if defined(doxygen)
1063  // Sanitized for documentation:
1064  template <class D>
1065  friend inline TfRefPtr<D> TfConst_cast(const TfRefPtr<const D>&);
1066 #else
1067  template <class D>
1070 #endif
1071 
1072  T* _GetData() const {
1073  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1074  }
1075 
1076  // This method is only used when calling the hook functions for
1077  // tracking. We reinterpret_cast instead of static_cast so that
1078  // we don't need the definition of T. However, if TfRefBase is
1079  // not the first base class of T then the resulting pointer may
1080  // not point to a T. Nevertheless, it should be consistent to
1081  // all calls to the tracking functions.
1082  T* _GetObjectForTracking() const {
1083  return reinterpret_cast<T*>(const_cast<TfRefBase*>(_refBase));
1084  }
1085 
1092 
1093  template <class U>
1094  friend const std::type_info& TfTypeid(const TfRefPtr<U>& ptr);
1095 
1096  void _AddRef() const {
1097  _Counter::AddRef(_refBase);
1098  }
1099 
1100  void _RemoveRef(const TfRefBase* ptr) const {
1101  if (_Counter::RemoveRef(ptr)) {
1102  Tf_RefPtrTracker_LastRef(this,
1103  reinterpret_cast<T*>(const_cast<TfRefBase*>(ptr)));
1104  delete ptr;
1105  }
1106  }
1107 
1108 #if ! defined(doxygen)
1109  // doxygen is very confused by this. It declares all TfRefPtrs
1110  // to be friends.
1111  template <class U> friend class TfRefPtr;
1112  template <class U> friend class TfWeakPtr;
1113  friend class Tf_Remnant;
1114 
1115  template <class U>
1117 #endif
1118  friend class TfWeakBase;
1119 };
1120 
1121 #if !defined(doxygen)
1122 
1123 //
1124 // nullptr comparisons
1125 //
1126 // These are provided to avoid ambiguous overloads due to
1127 // TfWeakPtrFacade::Derived comparisons with TfRefPtr.
1128 //
1129 
1130 template <class T>
1131 inline bool operator== (const TfRefPtr<T> &p, std::nullptr_t)
1132 {
1133  return !p;
1134 }
1135 template <class T>
1136 inline bool operator== (std::nullptr_t, const TfRefPtr<T> &p)
1137 {
1138  return !p;
1139 }
1140 
1141 template <class T>
1142 inline bool operator!= (const TfRefPtr<T> &p, std::nullptr_t)
1143 {
1144  return !(p == nullptr);
1145 }
1146 template <class T>
1147 inline bool operator!= (std::nullptr_t, const TfRefPtr<T> &p)
1148 {
1149  return !(nullptr == p);
1150 }
1151 
1152 template <class T>
1153 inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1154 {
1155  return std::less<const TfRefBase *>()(get_pointer(p), nullptr);
1156 }
1157 template <class T>
1158 inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1159 {
1160  return std::less<const TfRefBase *>()(nullptr, get_pointer(p));
1161 }
1162 
1163 template <class T>
1164 inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1165 {
1166  return !(nullptr < p);
1167 }
1168 template <class T>
1169 inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1170 {
1171  return !(p < nullptr);
1172 }
1173 
1174 template <class T>
1175 inline bool operator> (const TfRefPtr<T> &p, std::nullptr_t)
1176 {
1177  return nullptr < p;
1178 }
1179 template <class T>
1180 inline bool operator> (std::nullptr_t, const TfRefPtr<T> &p)
1181 {
1182  return p < nullptr;
1183 }
1184 
1185 template <class T>
1186 inline bool operator>= (const TfRefPtr<T> &p, std::nullptr_t)
1187 {
1188  return !(p < nullptr);
1189 }
1190 template <class T>
1191 inline bool operator>= (std::nullptr_t, const TfRefPtr<T> &p)
1192 {
1193  return !(nullptr < p);
1194 }
1195 
1196 
1197 template <typename T>
1198 inline TfRefPtr<T> TfCreateRefPtr(T* ptr) {
1199  return TfRefPtr<T>(ptr, typename TfRefPtr<T>::_CreateRefPtr());
1200 }
1201 
1202 template <class T>
1203 const std::type_info&
1204 TfTypeid(const TfRefPtr<T>& ptr)
1205 {
1206  if (ARCH_UNLIKELY(!ptr._refBase))
1207  TF_FATAL_ERROR("called TfTypeid on NULL TfRefPtr");
1208 
1209  return typeid(*ptr._GetData());
1210 }
1211 
1212 template <class D, class T>
1213 inline
1215 TfDynamic_cast(const TfRefPtr<T>& ptr)
1216 {
1217  typedef TfRefPtr<typename D::DataType> RefPtr;
1218  return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1219 }
1220 
1221 template <class D, class T>
1222 inline
1224 TfSafeDynamic_cast(const TfRefPtr<T>& ptr)
1225 {
1226  typedef TfRefPtr<typename D::DataType> RefPtr;
1227  return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1228 }
1229 
1230 template <class D, class T>
1231 inline
1233 TfStatic_cast(const TfRefPtr<T>& ptr)
1234 {
1235  typedef TfRefPtr<typename D::DataType> RefPtr;
1236  return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1237 }
1238 
1239 template <class T>
1240 inline
1242 TfConst_cast(const TfRefPtr<const typename T::DataType>& ptr)
1243 {
1244  // this ugly cast allows TfConst_cast to work without requiring
1245  // a definition for T.
1246  typedef TfRefPtr<typename T::DataType> NonConstRefPtr;
1247  return *((NonConstRefPtr*)(&ptr));
1248 }
1249 
1250 // Specialization: prevent construction of a TfRefPtr<TfRefBase>.
1251 
1252 template <>
1253 class TfRefPtr<TfRefBase> {
1254 private:
1256  }
1257 };
1258 
1259 template <>
1260 class TfRefPtr<const TfRefBase> {
1261 private:
1263  }
1264 };
1265 
1266 template <class T>
1267 struct TfTypeFunctions<TfRefPtr<T> > {
1268  static T* GetRawPtr(const TfRefPtr<T>& t) {
1269  return t.operator-> ();
1270  }
1271 
1272  static TfRefPtr<T> ConstructFromRawPtr(T* ptr) {
1273  return TfRefPtr<T>(ptr);
1274  }
1275 
1276  static bool IsNull(const TfRefPtr<T>& t) {
1277  return !t;
1278  }
1279 
1280  static void Class_Object_MUST_Be_Passed_By_Address() { }
1281  static void Class_Object_MUST_Not_Be_Const() { }
1282 };
1283 
1284 template <class T>
1285 struct TfTypeFunctions<TfRefPtr<const T> > {
1286  static const T* GetRawPtr(const TfRefPtr<const T>& t) {
1287  return t.operator-> ();
1288  }
1289 
1290  static TfRefPtr<const T> ConstructFromRawPtr(T* ptr) {
1291  return TfRefPtr<const T>(ptr);
1292  }
1293 
1294  static bool IsNull(const TfRefPtr<const T>& t) {
1295  return !t;
1296  }
1297 
1298  static void Class_Object_MUST_Be_Passed_By_Address() { }
1299 };
1300 
1301 #endif
1302 
1303 #if !defined(doxygen)
1304 
1305 template <class T>
1306 inline void
1307 swap(TfRefPtr<T>& lhs, TfRefPtr<T>& rhs)
1308 {
1309  lhs.swap(rhs);
1310 }
1311 
1312 PXR_NAMESPACE_CLOSE_SCOPE
1313 
1314 namespace boost {
1315 
1316 template<typename T>
1317 T *
1318 get_pointer(PXR_NS::TfRefPtr<T> const& p)
1319 {
1320  return get_pointer(p);
1321 }
1322 
1323 } // end namespace boost
1324 
1325 PXR_NAMESPACE_OPEN_SCOPE
1326 
1327 // Extend boost::hash to support TfRefPtr.
1328 template <class T>
1329 inline size_t
1330 hash_value(const TfRefPtr<T>& ptr)
1331 {
1332  // Make the boost::hash type depend on T so that we don't have to always
1333  // include boost/functional/hash.hpp in this header for the definition of
1334  // boost::hash.
1335  auto refBase = ptr._refBase;
1336  return boost::hash<decltype(refBase)>()(refBase);
1337 }
1338 
1339 template <class HashState, class T>
1340 inline void
1341 TfHashAppend(HashState &h, const TfRefPtr<T> &ptr)
1342 {
1343  h.Append(get_pointer(ptr));
1344 }
1345 
1346 #endif // !doxygen
1347 
1348 #define TF_SUPPORTS_REFPTR(T) std::is_base_of<TfRefBase, T>::value
1349 
1350 #if defined(ARCH_COMPILER_MSVC)
1351 // There is a bug in the compiler which means we have to provide this
1352 // implementation. See here for more information:
1353 // https://connect.microsoft.com/VisualStudio/Feedback/Details/2852624
1354 
1355 #define TF_REFPTR_CONST_VOLATILE_GET(x) \
1356  namespace boost \
1357  { \
1358  template<> \
1359  const volatile x* \
1360  get_pointer(const volatile x* p) \
1361  { \
1362  return p; \
1363  } \
1364  }
1365 #else
1366 #define TF_REFPTR_CONST_VOLATILE_GET(x)
1367 #endif
1368 
1369 PXR_NAMESPACE_CLOSE_SCOPE
1370 
1371 #endif // PXR_BASE_TF_REF_PTR_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:74
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
Definition: refPtr.h:694
TfRefPtr()
Initialize pointer to nullptr.
Definition: refPtr.h:598
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:847
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
Definition: refPtr.h:608
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:277
TO TfSafeDynamic_cast(FROM *ptr)
Safely perform a dynamic cast.
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:881
void Reset()
Set this pointer to point to no object.
Definition: refPtr.h:964
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.
Definition: refPtr.h:799
TfRefPtr< T > & operator=(const TfRefPtr< U > &p)
Assigns pointer to point at p's object, and increments reference count.
Definition: refPtr.h:820
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.
Definition: refPtr.h:586
void swap(TfRefPtr &other)
Swap this pointer with other.
Definition: refPtr.h:954
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
Compiler hints.
bool operator !() const
True if the pointer points to NULL.
Definition: refPtr.h:946
Pointer storage with deletion detection.
Definition: refBase.h:38
Enable a concrete base class for use with TfRefPtr.
Definition: refBase.h:71
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
Definition: refPtr.h:688
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.
Definition: refPtr.h:717
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.
Definition: diagnostic.h:108
TfRefPtr(const TfRefPtr< U > &p)
Initializes to point at p's object, and increments reference count.
Definition: refPtr.h:780
friend TfRefPtr< D > TfDynamic_cast(const TfRefPtr< T > &)
Allows dynamic casting of a TfRefPtr.
~TfRefPtr()
Decrements reference count of object being pointed to.
Definition: refPtr.h:764
T & operator *() const
Dereferences the stored pointer.
Definition: refPtr.h:932
std::enable_if< std::is_same< Half, half >::value, size_t >::type hash_value(const Half &h)
Overload hash_value for half.
Definition: half.h:50
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:893
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.
Definition: refPtr.h:745
friend TfRefPtr< D > TfConst_cast(const TfRefPtr< const D > &)
Allows const casting of a TfRefPtr.
Implements assorted functions based on compile-time type information.
Definition: typeFunctions.h:54
friend TfRefPtr< D > TfStatic_cast(const TfRefPtr< T > &)
Allows static casting of a TfRefPtr.
Reference-counted smart pointer utility class.
Definition: refBase.h:37
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:870
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
Definition: refPtr.h:678
T * operator->() const
Accessor to T's public members.
Definition: refPtr.h:923
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
Definition: refPtr.h:618
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
Stripped down version of diagnostic.h that doesn't define std::string.