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