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 #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>
444 
445 #include <typeinfo>
446 #include <type_traits>
447 #include <cstddef>
448 
449 PXR_NAMESPACE_OPEN_SCOPE
450 
451 // Tf_SupportsUniqueChanged is a metafunction that may be specialized to return
452 // false for classes (and all derived classes) that *cannot* ever invoke unique
453 // changed listeners.
454 template <class T>
455 struct Tf_SupportsUniqueChanged {
456  static const bool Value = true;
457 };
458 
459 // Remnants are never able to support weak changed listeners.
460 class Tf_Remnant;
461 template <>
462 struct Tf_SupportsUniqueChanged<Tf_Remnant> {
463  static const bool Value = false;
464 };
465 
466 class TfWeakBase;
467 
468 template <class T> class TfWeakPtr;
469 template <template <class> class X, class Y>
470 class TfWeakPtrFacade;
471 
472 // Functions used for tracking. Do not implement these.
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*) { }
478 
479 // This code is used to increment and decrement ref counts in the common case.
480 // It may lock and invoke the unique changed listener, if the reference count
481 // becomes unique or non-unique.
482 struct Tf_RefPtr_UniqueChangedCounter {
483  static inline int
484  AddRef(TfRefBase const *refBase)
485  {
486  if (refBase) {
487  // Check to see if we need to invoke the unique changed listener.
488  if (refBase->_shouldInvokeUniqueChangedListener)
489  return _AddRef(refBase);
490  else
491  return refBase->GetRefCount()._FetchAndAdd(1);
492  }
493  return 0;
494  }
495 
496  static inline bool
497  RemoveRef(TfRefBase const* refBase) {
498  if (refBase) {
499  // Check to see if we need to invoke the unique changed listener.
500  return refBase->_shouldInvokeUniqueChangedListener ?
501  _RemoveRef(refBase) :
502  refBase->GetRefCount()._DecrementAndTestIfZero();
503  }
504  return false;
505  }
506 
507  // Increment ptr's count if it is not zero. Return true if done so
508  // successfully, false if its count is zero.
509  static inline bool
510  AddRefIfNonzero(TfRefBase const *ptr) {
511  if (!ptr)
512  return false;
513  if (ptr->_shouldInvokeUniqueChangedListener) {
514  return _AddRefIfNonzero(ptr);
515  } else {
516  auto &counter = ptr->GetRefCount()._counter;
517  auto val = counter.load();
518  do {
519  if (val == 0)
520  return false;
521  } while (!counter.compare_exchange_weak(val, val + 1));
522  return true;
523  }
524  }
525 
526  TF_API static bool _RemoveRef(TfRefBase const *refBase);
527 
528  TF_API static int _AddRef(TfRefBase const *refBase);
529 
530  TF_API static bool _AddRefIfNonzero(TfRefBase const *refBase);
531 };
532 
533 // This code is used to increment and decrement ref counts in the case where
534 // the object pointed to explicitly does not support unique changed listeners.
535 struct Tf_RefPtr_Counter {
536  static inline int
537  AddRef(TfRefBase const *refBase) {
538  if (refBase)
539  return refBase->GetRefCount()._FetchAndAdd(1);
540  return 0;
541  }
542 
543  static inline bool
544  RemoveRef(TfRefBase const *ptr) {
545  return (ptr && (ptr->GetRefCount()._DecrementAndTestIfZero()));
546  }
547 
548  // Increment ptr's count if it is not zero. Return true if done so
549  // successfully, false if its count is zero.
550  static inline bool
551  AddRefIfNonzero(TfRefBase const *ptr) {
552  if (!ptr)
553  return false;
554  auto &counter = ptr->GetRefCount()._counter;
555  auto val = counter.load();
556  do {
557  if (val == 0)
558  return false;
559  } while (!counter.compare_exchange_weak(val, val + 1));
560  return true;
561  }
562 };
563 
564 // Helper to post a fatal error when a NULL Tf pointer is dereferenced.
565 [[noreturn]]
566 TF_API void
567 Tf_PostNullSmartPtrDereferenceFatalError(const TfCallContext &, const char *);
568 
580 template <class T>
581 class TfRefPtr {
582  // Select the counter based on whether T supports unique changed listeners.
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;
588 
589 public:
591  typedef T DataType;
592 
593 
594  template <class U> struct Rebind {
595  typedef TfRefPtr<U> Type;
596  };
597 
603  TfRefPtr() : _refBase(nullptr) {
604  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
605  }
606 
613  TfRefPtr(TfRefPtr<T>&& p) : _refBase(p._refBase) {
614  p._refBase = nullptr;
615  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
616  Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
617  _GetObjectForTracking());
618  }
619 
623  TfRefPtr(const TfRefPtr<T>& p) : _refBase(p._refBase) {
624  _AddRef();
625  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
626  }
627 
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*>
635  >::type *dummy = 0);
636 
669 #if defined(doxygen)
670  friend inline TfRefPtr TfCreateRefPtr(T*);
671 #else
672  template <class U>
673  friend inline TfRefPtr<U> TfCreateRefPtr(U*);
674 #endif
675 
682  template <class U>
683  explicit TfRefPtr(
684  U* ptr, typename std::enable_if<
685  std::is_convertible<U*, T*>::value>::type * = nullptr) :
686  _refBase(ptr)
687  {
688  _AddRef();
689  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
690  }
691 
693  TfRefPtr(TfNullPtrType) : _refBase(nullptr)
694  {
695  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
696  }
697 
699  TfRefPtr(std::nullptr_t) : _refBase(nullptr)
700  {
701  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
702  }
703 
723  //
724  // It is quite possible for
725  // ptr = TfNullPtr;
726  // to delete the space that ptr actually lives in (this happens
727  // when you use a circular reference to keep an object alive).
728  // To avoid a crash, we have to ensure that deletion of the object
729  // is the last thing done in the assignment; so we use some
730  // local variables to help us out.
731  //
732 
733  Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
734  _GetObjectForTracking());
735 
736  const TfRefBase* tmp = _refBase;
737  _refBase = p._refBase;
738 
739  p._AddRef(); // first!
740  _RemoveRef(tmp); // second!
741  return *this;
742  }
743 
751  // See comment in assignment operator.
752  Tf_RefPtrTracker_Assign(this, p._GetObjectForTracking(),
753  _GetObjectForTracking());
754  Tf_RefPtrTracker_Assign(&p, nullptr,
755  p._GetObjectForTracking());
756 
757  const TfRefBase* tmp = _refBase;
758  _refBase = p._refBase;
759  p._refBase = nullptr;
760 
761  _RemoveRef(tmp);
762  return *this;
763  }
764 
770  Tf_RefPtrTracker_Delete(this, _GetObjectForTracking());
771  _RemoveRef(_refBase);
772  }
773 
774 private:
775 
776  // Compile error if a U* cannot be assigned to a T*.
777  template <class U>
778  static void _CheckTypeAssignability() {
779  T* unused = (U*)0;
780  if (unused) unused = 0;
781  }
782 
783  // Compile error if a T* and U* cannot be compared.
784  template <class U>
785  static void _CheckTypeComparability() {
786  bool unused = ((T*)0 == (U*)0);
787  if (unused) unused = false;
788  }
789 
790 public:
791 
800 #if !defined(doxygen)
801  template <class U>
802 #endif
803  TfRefPtr(const TfRefPtr<U>& p) : _refBase(p._refBase) {
804  if (!boost::is_same<T,U>::value) {
805  if (false)
806  _CheckTypeAssignability<U>();
807  }
808 
809  _AddRef();
810  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
811  }
812 
823 #if !defined(doxygen)
824  template <class U>
825 #endif
826  TfRefPtr(TfRefPtr<U>&& p) : _refBase(p._refBase) {
827  if (!boost::is_same<T,U>::value) {
828  if (false)
829  _CheckTypeAssignability<U>();
830  }
831 
832  p._refBase = nullptr;
833  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
834  Tf_RefPtrTracker_Assign(&p, p._GetObjectForTracking(),
835  _GetObjectForTracking());
836  }
837 
848 #if !defined(doxygen)
849  template <class U>
850 #endif
852  if (!boost::is_same<T,U>::value) {
853  if (false)
854  _CheckTypeAssignability<U>();
855  }
856 
857  Tf_RefPtrTracker_Assign(this,
858  reinterpret_cast<T*>(p._GetObjectForTracking()),
859  _GetObjectForTracking());
860  const TfRefBase* tmp = _refBase;
861  _refBase = p._GetData();
862  p._AddRef(); // first!
863  _RemoveRef(tmp); // second!
864  return *this;
865  }
866 
878 #if !defined(doxygen)
879  template <class U>
880 #endif
882  if (!boost::is_same<T,U>::value) {
883  if (false)
884  _CheckTypeAssignability<U>();
885  }
886 
887  Tf_RefPtrTracker_Assign(this,
888  reinterpret_cast<T*>(p._GetObjectForTracking()),
889  _GetObjectForTracking());
890  Tf_RefPtrTracker_Assign(&p,
891  nullptr,
892  reinterpret_cast<T*>(p._GetObjectForTracking()));
893  const TfRefBase* tmp = _refBase;
894  _refBase = p._GetData();
895  p._refBase = nullptr;
896  _RemoveRef(tmp);
897  return *this;
898  }
899 
904 #if !defined(doxygen)
905  template <class U>
906 #endif
907  bool operator== (const TfRefPtr<U>& p) const {
908  if (false)
909  _CheckTypeComparability<U>();
910 
911  return _refBase == p._refBase;
912  }
913 
918 #if !defined(doxygen)
919  template <class U>
920 #endif
921  bool operator< (const TfRefPtr<U>& p) const {
922  if (false)
923  _CheckTypeComparability<U>();
924 
925  return _refBase < p._refBase;
926  }
927 
928 #if !defined(doxygen)
929  template <class U>
930 #endif
931  bool operator> (const TfRefPtr<U>& p) const {
932  if (false)
933  _CheckTypeComparability<U>();
934 
935  return _refBase > p._refBase;
936  }
937 
938 #if !defined(doxygen)
939  template <class U>
940 #endif
941  bool operator<= (const TfRefPtr<U>& p) const {
942  if (false)
943  _CheckTypeComparability<U>();
944 
945  return _refBase <= p._refBase;
946  }
947 
948 #if !defined(doxygen)
949  template <class U>
950 #endif
951  bool operator>= (const TfRefPtr<U>& p) const {
952  if (false)
953  _CheckTypeComparability<U>();
954 
955  return _refBase >= p._refBase;
956  }
957 
961 #if !defined(doxygen)
962  template <class U>
963 #endif
964  bool operator!= (const TfRefPtr<U>& p) const {
965  if (false)
966  _CheckTypeComparability<U>();
967 
968  return _refBase != p._refBase;
969  }
970 
972  T* operator ->() const {
973  if (_refBase) {
974  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
975  }
976  Tf_PostNullSmartPtrDereferenceFatalError(
977  TF_CALL_CONTEXT, typeid(TfRefPtr).name());
978  }
979 
981  T& operator *() const {
982  return *operator->();
983  }
984 
985 #if !defined(doxygen)
986  using UnspecifiedBoolType = const TfRefBase * (TfRefPtr::*);
987 #endif
988 
990  operator UnspecifiedBoolType() const {
991  return _refBase ? &TfRefPtr::_refBase : nullptr;
992  }
993 
995  bool operator !() const {
996  return _refBase == nullptr;
997  }
998 
1003  void swap(TfRefPtr &other) {
1004  Tf_RefPtrTracker_Assign(this, other._GetObjectForTracking(),
1005  _GetObjectForTracking());
1006  Tf_RefPtrTracker_Assign(&other, _GetObjectForTracking(),
1007  other._GetObjectForTracking());
1008  std::swap(_refBase, other._refBase);
1009  }
1010 
1013  void Reset() {
1014  *this = TfNullPtr;
1015  }
1016 
1017 private:
1018  const TfRefBase* _refBase;
1019 
1020  template <class HashState, class U>
1021  friend inline void TfHashAppend(HashState &, const TfRefPtr<U>&);
1022  template <class U>
1023  friend inline size_t hash_value(const TfRefPtr<U>&);
1024 
1025  friend T *get_pointer(TfRefPtr const &p) {
1026  return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
1027  }
1028 
1029  // Used to distinguish construction in TfCreateRefPtr.
1030  class _CreateRefPtr { };
1031 
1032  // private constructor, used by TfCreateRefPtr()
1033  TfRefPtr(T* ptr, _CreateRefPtr /* unused */)
1034  : _refBase(ptr)
1035  {
1036  /* reference count is NOT bumped */
1037  Tf_RefPtrTracker_FirstRef(this, _GetObjectForTracking());
1038  Tf_RefPtrTracker_New(this, _GetObjectForTracking());
1039  }
1040 
1041  // Hide confusing internals of actual C++ definition (e.g. DataType)
1042  // for doxygen output:
1043 
1059 #if defined(doxygen)
1060  // Sanitized for documentation:
1061  template <class D>
1062  friend inline TfRef<D> TfDynamic_cast(const TfRefPtr<T>&);
1063 #else
1064  template <class D, class B>
1066  TfDynamic_cast(const TfRefPtr<B>&);
1067 
1068  template <class D, class B>
1071 #endif
1072 
1089 #if defined(doxygen)
1090  // Sanitized for documentation:
1091  template <class D>
1092  friend inline TfRefPtr<D> TfStatic_cast(const TfRefPtr<T>&);
1093 #else
1094  template <class D, class B>
1096  TfStatic_cast(const TfRefPtr<B>&);
1097 
1098 #endif
1099 
1111 #if defined(doxygen)
1112  // Sanitized for documentation:
1113  template <class D>
1114  friend inline TfRefPtr<D> TfConst_cast(const TfRefPtr<const D>&);
1115 #else
1116  template <class D>
1119 #endif
1120 
1121  T* _GetData() const {
1122  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1123  }
1124 
1125  // This method is only used when calling the hook functions for
1126  // tracking. We reinterpret_cast instead of static_cast so that
1127  // we don't need the definition of T. However, if TfRefBase is
1128  // not the first base class of T then the resulting pointer may
1129  // not point to a T. Nevertheless, it should be consistent to
1130  // all calls to the tracking functions.
1131  T* _GetObjectForTracking() const {
1132  return reinterpret_cast<T*>(const_cast<TfRefBase*>(_refBase));
1133  }
1134 
1141 
1142  template <class U>
1143  friend const std::type_info& TfTypeid(const TfRefPtr<U>& ptr);
1144 
1145  void _AddRef() const {
1146  _Counter::AddRef(_refBase);
1147  }
1148 
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)));
1153  delete ptr;
1154  }
1155  }
1156 
1157 #if ! defined(doxygen)
1158  // doxygen is very confused by this. It declares all TfRefPtrs
1159  // to be friends.
1160  template <class U> friend class TfRefPtr;
1161  template <class U> friend class TfWeakPtr;
1162  friend class Tf_Remnant;
1163 
1164  template <class U>
1166 #endif
1167  friend class TfWeakBase;
1168 };
1169 
1170 #if !defined(doxygen)
1171 
1172 //
1173 // nullptr comparisons
1174 //
1175 // These are provided to avoid ambiguous overloads due to
1176 // TfWeakPtrFacade::Derived comparisons with TfRefPtr.
1177 //
1178 
1179 template <class T>
1180 inline bool operator== (const TfRefPtr<T> &p, std::nullptr_t)
1181 {
1182  return !p;
1183 }
1184 template <class T>
1185 inline bool operator== (std::nullptr_t, const TfRefPtr<T> &p)
1186 {
1187  return !p;
1188 }
1189 
1190 template <class T>
1191 inline bool operator!= (const TfRefPtr<T> &p, std::nullptr_t)
1192 {
1193  return !(p == nullptr);
1194 }
1195 template <class T>
1196 inline bool operator!= (std::nullptr_t, const TfRefPtr<T> &p)
1197 {
1198  return !(nullptr == p);
1199 }
1200 
1201 template <class T>
1202 inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1203 {
1204  return std::less<const TfRefBase *>()(get_pointer(p), nullptr);
1205 }
1206 template <class T>
1207 inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1208 {
1209  return std::less<const TfRefBase *>()(nullptr, get_pointer(p));
1210 }
1211 
1212 template <class T>
1213 inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1214 {
1215  return !(nullptr < p);
1216 }
1217 template <class T>
1218 inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1219 {
1220  return !(p < nullptr);
1221 }
1222 
1223 template <class T>
1224 inline bool operator> (const TfRefPtr<T> &p, std::nullptr_t)
1225 {
1226  return nullptr < p;
1227 }
1228 template <class T>
1229 inline bool operator> (std::nullptr_t, const TfRefPtr<T> &p)
1230 {
1231  return p < nullptr;
1232 }
1233 
1234 template <class T>
1235 inline bool operator>= (const TfRefPtr<T> &p, std::nullptr_t)
1236 {
1237  return !(p < nullptr);
1238 }
1239 template <class T>
1240 inline bool operator>= (std::nullptr_t, const TfRefPtr<T> &p)
1241 {
1242  return !(nullptr < p);
1243 }
1244 
1245 
1246 template <typename T>
1247 inline TfRefPtr<T> TfCreateRefPtr(T* ptr) {
1248  return TfRefPtr<T>(ptr, typename TfRefPtr<T>::_CreateRefPtr());
1249 }
1250 
1251 template <class T>
1252 const std::type_info&
1253 TfTypeid(const TfRefPtr<T>& ptr)
1254 {
1255  if (ARCH_UNLIKELY(!ptr._refBase))
1256  TF_FATAL_ERROR("called TfTypeid on NULL TfRefPtr");
1257 
1258  return typeid(*ptr._GetData());
1259 }
1260 
1261 template <class D, class T>
1262 inline
1264 TfDynamic_cast(const TfRefPtr<T>& ptr)
1265 {
1266  typedef TfRefPtr<typename D::DataType> RefPtr;
1267  return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1268 }
1269 
1270 template <class D, class T>
1271 inline
1273 TfSafeDynamic_cast(const TfRefPtr<T>& ptr)
1274 {
1275  typedef TfRefPtr<typename D::DataType> RefPtr;
1276  return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1277 }
1278 
1279 template <class D, class T>
1280 inline
1282 TfStatic_cast(const TfRefPtr<T>& ptr)
1283 {
1284  typedef TfRefPtr<typename D::DataType> RefPtr;
1285  return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1286 }
1287 
1288 template <class T>
1289 inline
1291 TfConst_cast(const TfRefPtr<const typename T::DataType>& ptr)
1292 {
1293  // this ugly cast allows TfConst_cast to work without requiring
1294  // a definition for T.
1295  typedef TfRefPtr<typename T::DataType> NonConstRefPtr;
1296  return *((NonConstRefPtr*)(&ptr));
1297 }
1298 
1299 // Specialization: prevent construction of a TfRefPtr<TfRefBase>.
1300 
1301 template <>
1302 class TfRefPtr<TfRefBase> {
1303 private:
1305  }
1306 };
1307 
1308 template <>
1309 class TfRefPtr<const TfRefBase> {
1310 private:
1312  }
1313 };
1314 
1315 template <class T>
1316 struct TfTypeFunctions<TfRefPtr<T> > {
1317  static T* GetRawPtr(const TfRefPtr<T>& t) {
1318  return t.operator-> ();
1319  }
1320 
1321  static TfRefPtr<T> ConstructFromRawPtr(T* ptr) {
1322  return TfRefPtr<T>(ptr);
1323  }
1324 
1325  static bool IsNull(const TfRefPtr<T>& t) {
1326  return !t;
1327  }
1328 
1329  static void Class_Object_MUST_Be_Passed_By_Address() { }
1330  static void Class_Object_MUST_Not_Be_Const() { }
1331 };
1332 
1333 template <class T>
1334 struct TfTypeFunctions<TfRefPtr<const T> > {
1335  static const T* GetRawPtr(const TfRefPtr<const T>& t) {
1336  return t.operator-> ();
1337  }
1338 
1339  static TfRefPtr<const T> ConstructFromRawPtr(T* ptr) {
1340  return TfRefPtr<const T>(ptr);
1341  }
1342 
1343  static bool IsNull(const TfRefPtr<const T>& t) {
1344  return !t;
1345  }
1346 
1347  static void Class_Object_MUST_Be_Passed_By_Address() { }
1348 };
1349 
1350 #endif
1351 
1352 #if !defined(doxygen)
1353 
1354 template <class T>
1355 inline void
1356 swap(TfRefPtr<T>& lhs, TfRefPtr<T>& rhs)
1357 {
1358  lhs.swap(rhs);
1359 }
1360 
1361 PXR_NAMESPACE_CLOSE_SCOPE
1362 
1363 namespace boost {
1364 
1365 template<typename T>
1366 T *
1367 get_pointer(PXR_NS::TfRefPtr<T> const& p)
1368 {
1369  return get_pointer(p);
1370 }
1371 
1372 } // end namespace boost
1373 
1374 PXR_NAMESPACE_OPEN_SCOPE
1375 
1376 // Extend boost::hash to support TfRefPtr.
1377 template <class T>
1378 inline size_t
1379 hash_value(const TfRefPtr<T>& ptr)
1380 {
1381  // Make the boost::hash type depend on T so that we don't have to always
1382  // include boost/functional/hash.hpp in this header for the definition of
1383  // boost::hash.
1384  auto refBase = ptr._refBase;
1385  return boost::hash<decltype(refBase)>()(refBase);
1386 }
1387 
1388 template <class HashState, class T>
1389 inline void
1390 TfHashAppend(HashState &h, const TfRefPtr<T> &ptr)
1391 {
1392  h.Append(get_pointer(ptr));
1393 }
1394 
1395 #endif // !doxygen
1396 
1397 #define TF_SUPPORTS_REFPTR(T) boost::is_base_of<TfRefBase, T >::value
1398 
1399 #if defined(ARCH_COMPILER_MSVC)
1400 // There is a bug in the compiler which means we have to provide this
1401 // implementation. See here for more information:
1402 // https://connect.microsoft.com/VisualStudio/Feedback/Details/2852624
1403 
1404 #define TF_REFPTR_CONST_VOLATILE_GET(x) \
1405  namespace boost \
1406  { \
1407  template<> \
1408  const volatile x* \
1409  get_pointer(const volatile x* p) \
1410  { \
1411  return p; \
1412  } \
1413  }
1414 #else
1415 #define TF_REFPTR_CONST_VOLATILE_GET(x)
1416 #endif
1417 
1418 PXR_NAMESPACE_CLOSE_SCOPE
1419 
1420 #endif // PXR_BASE_TF_REF_PTR_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:61
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
Definition: refPtr.h:699
TfRefPtr()
Initialize pointer to nullptr.
Definition: refPtr.h:603
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:881
TfRefPtr(TfRefPtr< T > &&p)
Moves the pointer managed by p to *this.
Definition: refPtr.h:613
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.
void Reset()
Set this pointer to point to no object.
Definition: refPtr.h:1013
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:826
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.
Definition: refPtr.h:851
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:591
void swap(TfRefPtr &other)
Swap this pointer with other.
Definition: refPtr.h:1003
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:995
Pointer storage with deletion detection.
Definition: refBase.h:38
Enable a concrete base class for use with TfRefPtr.
Definition: refBase.h:71
bool operator!=(const TfRefPtr< U > &p) const
Returns true if *this and p do not point to the same object.
Definition: refPtr.h:964
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
Definition: refPtr.h:693
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:722
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:803
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).
Definition: refPtr.h:907
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...
Definition: refPtr.h:921
~TfRefPtr()
Decrements reference count of object being pointed to.
Definition: refPtr.h:769
T & operator *() const
Dereferences the stored pointer.
Definition: refPtr.h:981
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
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:750
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
T * operator ->() const
Accessor to T's public members.
Definition: refPtr.h:972
friend TfRefPtr< D > TfStatic_cast(const TfRefPtr< T > &)
Allows static casting of a TfRefPtr.
Reference-counted smart pointer utility class.
Definition: refBase.h:37
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Initializes to point at *ptr.
Definition: refPtr.h:683
TfRefPtr(const TfRefPtr< T > &p)
Initializes *this to point at p's object.
Definition: refPtr.h:623
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.