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