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