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