weakPtrFacade.h
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_WEAK_PTR_FACADE_H
8 #define PXR_BASE_TF_WEAK_PTR_FACADE_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/base/tf/diagnostic.h"
13 #include "pxr/base/tf/hash.h"
14 #include "pxr/base/tf/refPtr.h"
15 #include "pxr/base/tf/weakBase.h"
16 
17 #include "pxr/base/arch/demangle.h"
18 
19 #include <type_traits>
20 
21 PXR_NAMESPACE_OPEN_SCOPE
22 
23 template <class U> class TfRefPtr;
24 
25 template <template <class> class PtrTemplate, class DataType>
26 class TfWeakPtrFacade;
27 
34 public:
35  template <template <class> class PtrTemplate, class DataType>
36  friend class TfWeakPtrFacade;
37 
38  template <class Facade>
39  static typename Facade::DataType *FetchPointer(Facade const &f) {
40  return f._FetchPointer();
41  }
42 
43  template <class Facade>
44  static void const *GetUniqueIdentifier(Facade const &f) {
45  return f._GetUniqueIdentifier();
46  }
47 
48  template <class Facade>
49  static void EnableExtraNotification(Facade const &f) {
50  return f._EnableExtraNotification();
51  }
52 
53  template <class Facade>
54  static bool IsInvalid(Facade const &f) {
55  return f._IsInvalid();
56  }
57 
58 private:
60 };
61 
62 template <template <class> class X, class Y>
63 Y *get_pointer(TfWeakPtrFacade<X, Y> const &p) {
64  return TfWeakPtrFacadeAccess::FetchPointer(p);
65 }
66 
67 // Common base class, used to identify subtypes in enable_if expressions.
68 class TfWeakPtrFacadeBase {};
69 
70 template <template <class> class PtrTemplate, class Type>
71 class TfWeakPtrFacade : public TfWeakPtrFacadeBase {
72 
73 public:
74 
75  friend class TfWeakPtrFacadeAccess;
76 
77  typedef Type DataType;
78  typedef PtrTemplate<DataType> Derived;
79  typedef TfWeakPtrFacadeAccess Access;
80 
81  typedef Type element_type;
82 
83  template <class Other>
84  bool operator == (PtrTemplate<Other> const &p) const {
85  if (false)
86  return _FetchPointer() == TfWeakPtrFacadeAccess::FetchPointer(p);
87  return GetUniqueIdentifier() == p.GetUniqueIdentifier();
88  }
89 
90  template <class Other>
91  bool operator != (PtrTemplate<Other> const &p) const {
92  return !(*this == p);
93  }
94 
95  template <class T>
96  bool operator == (TfRefPtr<T> const &p) const {
97  if (!GetUniqueIdentifier())
98  return !p;
99  DataType *ptr = _FetchPointer();
100  return ptr && ptr == get_pointer(p);
101  }
102 
103  template <class T>
104  bool operator != (TfRefPtr<T> const &p) const {
105  return !(*this == p);
106  }
107 
108  template <class T>
109  friend bool operator == (const TfRefPtr<T>& p1, Derived const &p2) {
110  return p2.operator==(p1);
111  }
112 
113  template <class T>
114  friend bool operator != (const TfRefPtr<T>& p1, Derived const &p2) {
115  return !(p1 == p2);
116  }
117 
118  template <class Other>
119  bool operator < (PtrTemplate<Other> const &p) const {
120  if (false)
121  return _FetchPointer() < TfWeakPtrFacadeAccess::FetchPointer(p);
122  return GetUniqueIdentifier() < p.GetUniqueIdentifier();
123  }
124 
125  template <class Other>
126  bool operator > (PtrTemplate<Other> const &p) const {
127  return !(*this < p) && !(*this == p);
128  }
129 
130  template <class Other>
131  bool operator <= (PtrTemplate<Other> const &p) const {
132  return (*this < p) || (*this == p);
133  }
134 
135  template <class Other>
136  bool operator >= (PtrTemplate<Other> const &p) const {
137  return !(*this < p);
138  }
139 
140  using UnspecifiedBoolType = DataType * (TfWeakPtrFacade::*)(void) const;
141 
142  operator UnspecifiedBoolType () const {
143  return _FetchPointer() ? &TfWeakPtrFacade::_FetchPointer : nullptr;
144  }
145 
146  bool operator ! () const {
147  return !(bool(*this));
148  }
149 
150  template <class T>
151  bool PointsTo(T const &obj) const {
152  return _FetchPointer() == &obj;
153  }
154 
158  template <class T>
159  bool PointsToA() const {
160  return dynamic_cast<T *>(_FetchPointer());
161  }
162 
163  bool IsInvalid() const {
164  return Access::IsInvalid(_Derived());
165  }
166 
167  void const *GetUniqueIdentifier() const {
168  return Access::GetUniqueIdentifier(_Derived());
169  }
170 
171  TfWeakBase const *GetWeakBase() const {
172  return &_Derived()->__GetTfWeakBase__();
173  }
174 
175  void EnableExtraNotification() const {
176  Access::EnableExtraNotification(_Derived());
177  }
178 
179  DataType *operator -> () const {
180  DataType *ptr = _FetchPointer();
181  if (ptr) {
182  return ptr;
183  }
184  Tf_PostNullSmartPtrDereferenceFatalError(
185  TF_CALL_CONTEXT, typeid(Derived).name());
186  }
187 
188  DataType &operator * () const {
189  return * operator->();
190  }
191 
194  void Reset() {
195  _Derived() = TfNullPtr;
196  }
197 
198 private:
199 
200  friend std::type_info const &TfTypeid(Derived const &p) {
201  if (ARCH_UNLIKELY(!p))
202  TF_FATAL_ERROR("Called TfTypeid on invalid %s",
203  ArchGetDemangled(typeid(Derived)).c_str());
204  return typeid(*get_pointer(p));
205  }
206 
207  DataType *_FetchPointer() const {
208  return Access::FetchPointer(_Derived());
209  }
210 
211  Derived &_Derived() {
212  return static_cast<Derived &>(*this);
213  }
214 
215  Derived const &_Derived() const {
216  return static_cast<Derived const &>(*this);
217  }
218 
219 };
220 
221 
230 
231 template <template <class> class X, class Y>
232 inline bool operator== (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
233 {
234  return !p;
235 }
236 template <template <class> class X, class Y>
237 inline bool operator== (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
238 {
239  return !p;
240 }
241 
242 template <template <class> class X, class Y>
243 inline bool operator!= (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
244 {
245  return !(p == nullptr);
246 }
247 template <template <class> class X, class Y>
248 inline bool operator!= (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
249 {
250  return !(nullptr == p);
251 }
252 
253 template <template <class> class X, class Y>
254 inline bool operator< (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
255 {
256  return std::less<void const *>()(p.GetUniqueIdentifier(), nullptr);
257 }
258 template <template <class> class X, class Y>
259 inline bool operator< (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
260 {
261  return std::less<void const *>()(nullptr, p.GetUniqueIdentifier());
262 }
263 
264 template <template <class> class X, class Y>
265 inline bool operator<= (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
266 {
267  return !(nullptr < p);
268 }
269 template <template <class> class X, class Y>
270 inline bool operator<= (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
271 {
272  return !(p < nullptr);
273 }
274 
275 template <template <class> class X, class Y>
276 inline bool operator> (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
277 {
278  return nullptr < p;
279 }
280 template <template <class> class X, class Y>
281 inline bool operator> (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
282 {
283  return p < nullptr;
284 }
285 
286 template <template <class> class X, class Y>
287 inline bool operator>= (TfWeakPtrFacade<X, Y> const &p, std::nullptr_t)
288 {
289  return !(p < nullptr);
290 }
291 template <template <class> class X, class Y>
292 inline bool operator>= (std::nullptr_t, TfWeakPtrFacade<X, Y> const &p)
293 {
294  return !(nullptr < p);
295 }
296 
298 
299 template <class ToPtr, template <class> class X, class Y>
300 ToPtr TfDynamic_cast(TfWeakPtrFacade<X, Y> const &p) {
301  return ToPtr(dynamic_cast<typename ToPtr::DataType *>
302  (get_pointer(p)));
303 }
304 
305 template <class ToPtr, template <class> class X, class Y>
306 ToPtr TfSafeDynamic_cast(TfWeakPtrFacade<X, Y> const &p) {
307  return ToPtr(TfSafeDynamic_cast<typename ToPtr::DataType *>
308  (get_pointer(p)));
309 }
310 
311 template <class ToPtr, template <class> class X, class Y>
312 ToPtr TfStatic_cast(TfWeakPtrFacade<X, Y> const &p) {
313  return ToPtr(static_cast<typename ToPtr::DataType *>
314  (get_pointer(p)));
315 }
316 
317 template <class ToPtr, template <class> class X, class Y>
318 ToPtr TfConst_cast(TfWeakPtrFacade<X, Y> const &p) {
319  return ToPtr(const_cast<typename ToPtr::DataType *>
320  (get_pointer(p)));
321 }
322 
323 //
324 // This is the implementation; the declaration and doxygen
325 // is in refPtr.h.
326 //
327 // If _remnant itself is NULL, then wp doesn't point to anything.
328 //
329 
330 template <class T>
331 template <template <class> class X, class U>
332 inline TfRefPtr<T>::TfRefPtr(const TfWeakPtrFacade<X, U>& p,
333  typename std::enable_if<
334  std::is_convertible<U*, T*>::value
335  >::type *)
336  : _refBase(get_pointer(p))
337 {
338  _AddRef();
339  Tf_RefPtrTracker_New(this, _refBase, _NullT);
340 }
341 
342 //
343 // See typeFunctions.h for documention.
344 //
345 template <template <class> class Ptr, class T>
346 struct TfTypeFunctions<Ptr<T>,
347  std::enable_if_t<
348  std::is_base_of<TfWeakPtrFacadeBase, Ptr<T>>::value
349  >>
350 {
351  static T* GetRawPtr(const Ptr<T>& t) {
352  return get_pointer(t);
353  }
354 
355  static Ptr<T> ConstructFromRawPtr(T* ptr) {
356  return Ptr<T>(ptr);
357  }
358 
359  static bool IsNull(const Ptr<T>& t) {
360  return !t;
361  }
362 
363  static void Class_Object_MUST_Be_Passed_By_Address() { }
364  static void Class_Object_MUST_Not_Be_Const() { }
365 };
366 
367 template <template <class> class Ptr, class T>
368 struct TfTypeFunctions<Ptr<const T>,
369  std::enable_if_t<
370  std::is_base_of<TfWeakPtrFacadeBase, Ptr<const T>>::value
371  >>
372 {
373  static const T* GetRawPtr(const Ptr<const T>& t) {
374  return get_pointer(t);
375  }
376 
377  static Ptr<const T> ConstructFromRawPtr(const T* ptr) {
378  return Ptr<const T>(ptr);
379  }
380 
381  static bool IsNull(const Ptr<const T>& t) {
382  return !t;
383  }
384 
385  static void Class_Object_MUST_Be_Passed_By_Address() { }
386 };
387 
388 // TfHash support.
389 template <class HashState, template <class> class X, class T>
390 inline void
391 TfHashAppend(HashState &h, TfWeakPtrFacade<X, T> const &ptr)
392 {
393  return h.Append(ptr.GetUniqueIdentifier());
394 }
395 
396 // Extend boost::hash to support TfWeakPtrFacade.
397 template <template <class> class X, class T>
398 inline size_t
399 hash_value(TfWeakPtrFacade<X, T> const &ptr)
400 {
401  return TfHash()(ptr);
402 }
403 
404 PXR_NAMESPACE_CLOSE_SCOPE
405 
406 #endif // PXR_BASE_TF_WEAK_PTR_FACADE_H
TfRefPtr()
Initialize pointer to nullptr.
Definition: refPtr.h:614
TO TfSafeDynamic_cast(FROM *ptr)
Safely perform a dynamic cast.
std::size_t hash_value(const half h)
Overload hash_value for half.
Definition: half.h:30
SdfHandle< typename DST::SpecType > TfStatic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle<SRC> x to an SdfHandle<DST>.
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Return demangled RTTI-generated type name.
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:602
Low-level utilities for informing users of various internal and external diagnostic conditions.
AR_API bool operator==(const ArAssetInfo &lhs, const ArAssetInfo &rhs)
Demangle C++ typenames generated by the typeid() facility.
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:472
SdfHandle< typename DST::SpecType > TfDynamic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle<SRC> x to an SdfHandle<DST>.
This access class is befriended by TfWeakPtrFacade -derived classes to grant TfWeakPtrFacade access t...
Definition: weakPtrFacade.h:33
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:92
Reference counting.
Implements assorted functions based on compile-time type information.
Definition: typeFunctions.h:37
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
Reference-counted smart pointer utility class.
Definition: refBase.h:22
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124