All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
anyWeakPtr.h
Go to the documentation of this file.
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_ANY_WEAK_PTR_H
25 #define PXR_BASE_TF_ANY_WEAK_PTR_H
26 
30 
31 #include "pxr/pxr.h"
32 #include "pxr/base/tf/api.h"
33 #include "pxr/base/tf/cxxCast.h"
34 #include "pxr/base/tf/type.h"
35 #include "pxr/base/tf/weakPtr.h"
36 
37 #ifdef PXR_PYTHON_SUPPORT_ENABLED
38 #include "pxr/base/tf/pyUtils.h"
39 #include <boost/python/object.hpp>
40 #endif // PXR_PYTHON_SUPPORT_ENABLED
41 
42 #include <boost/operators.hpp>
43 
44 #include <cstddef>
45 #include <type_traits>
46 #include <utility>
47 
48 PXR_NAMESPACE_OPEN_SCOPE
49 
54 class TfAnyWeakPtr : boost::totally_ordered<TfAnyWeakPtr>
55 {
56  struct _Data {
57  void* space[4];
58  };
59 
60 public:
61  typedef TfAnyWeakPtr This;
62 
64  template <class Ptr, class = typename
65  std::enable_if<Tf_SupportsWeakPtr<
66  typename Ptr::DataType>::value>::type>
67  TfAnyWeakPtr(Ptr const &ptr) {
68  static_assert(sizeof(_PointerHolder<Ptr>) <= sizeof(_Data),
69  "Ptr is too big to fit in a TfAnyWeakPtr");
70  new (&_ptrStorage) _PointerHolder<Ptr>(ptr);
71  }
72 
75  static_assert(sizeof(_EmptyHolder) <= sizeof(_Data),
76  "Ptr is too big to fit in a TfAnyWeakPtr");
77  new (&_ptrStorage) _EmptyHolder;
78  }
79 
81  TfAnyWeakPtr(TfNullPtrType) : TfAnyWeakPtr() {}
82 
84  TfAnyWeakPtr(std::nullptr_t) : TfAnyWeakPtr() {}
85 
86  TfAnyWeakPtr(TfAnyWeakPtr const &other) {
87  other._Get()->Clone(&_ptrStorage);
88  }
89 
90  TfAnyWeakPtr &operator=(TfAnyWeakPtr const &other) {
91  if (this != &other) {
92  _Get()->~_PointerHolderBase();
93  other._Get()->Clone(&_ptrStorage);
94  }
95  return *this;
96  }
97 
98  ~TfAnyWeakPtr() {
99  _Get()->~_PointerHolderBase();
100  }
101 
104  TF_API bool IsInvalid() const;
105 
107  TF_API void const *GetUniqueIdentifier() const;
108 
110  TF_API TfWeakBase const *GetWeakBase() const;
111 
113  TF_API operator bool() const;
114 
116  TF_API bool operator !() const;
117 
119  TF_API bool operator ==(const TfAnyWeakPtr &rhs) const;
120 
122  TF_API bool operator <(const TfAnyWeakPtr &rhs) const;
123 
125  TF_API const std::type_info & GetTypeInfo() const;
126 
128  TF_API TfType const& GetType() const;
129 
131  size_t GetHash() const {
132  return reinterpret_cast<uintptr_t>(GetUniqueIdentifier()) >> 3;
133  }
134 
135  private:
136 #ifdef PXR_PYTHON_SUPPORT_ENABLED
137  // This grants friend access to a function in the wrapper file for this
138  // class. This lets the wrapper reach down into an AnyWeakPtr to get a
139  // boost::python wrapped object corresponding to the held type. This
140  // facility is necessary to get the python API we want.
141  friend boost::python::api::object
142  Tf_GetPythonObjectFromAnyWeakPtr(This const &self);
143 
144  TF_API
145  boost::python::api::object _GetPythonObject() const;
146 #endif // PXR_PYTHON_SUPPORT_ENABLED
147 
148  template <class WeakPtr>
149  friend WeakPtr TfAnyWeakPtrDynamicCast(const TfAnyWeakPtr &anyWeak, WeakPtr*);
150 
151  // This is using the standard type-erasure pattern.
152  struct _PointerHolderBase {
153  TF_API virtual ~_PointerHolderBase();
154  virtual void Clone(_Data *target) const = 0;
155  virtual bool IsInvalid() const = 0;
156  virtual void const * GetUniqueIdentifier() const = 0;
157  virtual TfWeakBase const *GetWeakBase() const = 0;
158  virtual operator bool() const = 0;
159  virtual bool _IsConst() const = 0;
160 #ifdef PXR_PYTHON_SUPPORT_ENABLED
161  virtual boost::python::api::object GetPythonObject() const = 0;
162 #endif // PXR_PYTHON_SUPPORT_ENABLED
163  virtual const std::type_info & GetTypeInfo() const = 0;
164  virtual TfType const& GetType() const = 0;
165  virtual const void* _GetMostDerivedPtr() const = 0;
166  virtual bool _IsPolymorphic() const = 0;
167  };
168 
169  struct _EmptyHolder : _PointerHolderBase {
170  TF_API virtual ~_EmptyHolder();
171  TF_API virtual void Clone(_Data *target) const;
172  TF_API virtual bool IsInvalid() const;
173  TF_API virtual void const * GetUniqueIdentifier() const;
174  TF_API virtual TfWeakBase const *GetWeakBase() const;
175  TF_API virtual operator bool() const;
176  TF_API virtual bool _IsConst() const;
177 #ifdef PXR_PYTHON_SUPPORT_ENABLED
178  TF_API virtual boost::python::api::object GetPythonObject() const;
179 #endif // PXR_PYTHON_SUPPORT_ENABLED
180  TF_API virtual const std::type_info & GetTypeInfo() const;
181  TF_API virtual TfType const& GetType() const;
182  TF_API virtual const void* _GetMostDerivedPtr() const;
183  TF_API virtual bool _IsPolymorphic() const;
184  };
185 
186  template <typename Ptr>
187  struct _PointerHolder : _PointerHolderBase {
188  _PointerHolder(Ptr const &ptr) : _ptr(ptr) {
189  }
190 
191  virtual ~_PointerHolder();
192  virtual void Clone(_Data *target) const;
193  virtual bool IsInvalid() const;
194  virtual void const *GetUniqueIdentifier() const;
195  virtual TfWeakBase const *GetWeakBase() const;
196  virtual operator bool() const;
197  virtual bool _IsConst() const;
198 #ifdef PXR_PYTHON_SUPPORT_ENABLED
199  virtual boost::python::api::object GetPythonObject() const;
200 #endif // PXR_PYTHON_SUPPORT_ENABLED
201  virtual const std::type_info & GetTypeInfo() const;
202  virtual TfType const& GetType() const;
203  virtual const void* _GetMostDerivedPtr() const;
204  virtual bool _IsPolymorphic() const;
205  private:
206  Ptr _ptr;
207  };
208 
209  _PointerHolderBase* _Get() const {
210  return (_PointerHolderBase*)(&_ptrStorage);
211  }
212 
213  _Data _ptrStorage;
214 };
215 
216 // TfHash support. We don't want to choose the TfAnyWeakPtr overload unless the
217 // passed argument is exactly TfAnyWeakPtr. By making this a function template
218 // that's only enabled for TfAnyWeakPtr, C++ will not perform implicit
219 // conversions since T is deduced.
220 template <class HashState,
221  class T, class = typename std::enable_if<
222  std::is_same<T, TfAnyWeakPtr>::value>::type>
223 inline void
224 TfHashAppend(HashState &h, const T& ptr)
225 {
226  h.Append(ptr.GetUniqueIdentifier());
227 }
228 
229 template <class Ptr>
230 TfAnyWeakPtr::_PointerHolder<Ptr>::~_PointerHolder() {}
231 
232 template <class Ptr>
233 void
234 TfAnyWeakPtr::_PointerHolder<Ptr>::Clone(_Data *target) const
235 {
236  new (target) _PointerHolder<Ptr>(_ptr);
237 }
238 
239 template <class Ptr>
240 bool
241 TfAnyWeakPtr::_PointerHolder<Ptr>::IsInvalid() const
242 {
243  return _ptr.IsInvalid();
244 }
245 
246 template <class Ptr>
247 void const *
248 TfAnyWeakPtr::_PointerHolder<Ptr>::GetUniqueIdentifier() const
249 {
250  return _ptr.GetUniqueIdentifier();
251 }
252 
253 template <class Ptr>
254 TfWeakBase const *
255 TfAnyWeakPtr::_PointerHolder<Ptr>::GetWeakBase() const
256 {
257  return &(_ptr->__GetTfWeakBase__());
258 }
259 
260 template <class Ptr>
261 TfAnyWeakPtr::_PointerHolder<Ptr>::operator bool() const
262 {
263  return bool(_ptr);
264 }
265 
266 #ifdef PXR_PYTHON_SUPPORT_ENABLED
267 template <class Ptr>
268 boost::python::api::object
269 TfAnyWeakPtr::_PointerHolder<Ptr>::GetPythonObject() const
270 {
271  return TfPyObject(_ptr);
272 }
273 #endif // PXR_PYTHON_SUPPORT_ENABLED
274 
275 template <class Ptr>
276 const std::type_info &
277 TfAnyWeakPtr::_PointerHolder<Ptr>::GetTypeInfo() const
278 {
279  return TfTypeid(_ptr);
280 }
281 
282 template <class Ptr>
283 TfType const&
284 TfAnyWeakPtr::_PointerHolder<Ptr>::GetType() const
285 {
286  return TfType::Find(_ptr);
287 }
288 
289 template <class Ptr>
290 const void *
291 TfAnyWeakPtr::_PointerHolder<Ptr>::_GetMostDerivedPtr() const
292 {
293  if (!_ptr) {
294  return 0;
295  }
296 
297  typename Ptr::DataType const *rawPtr = get_pointer(_ptr);
298  return TfCastToMostDerivedType(rawPtr);
299 }
300 
301 template <class Ptr>
302 bool
303 TfAnyWeakPtr::_PointerHolder<Ptr>::_IsPolymorphic() const
304 {
305  return std::is_polymorphic<typename Ptr::DataType>::value;
306 }
307 
308 template <class Ptr>
309 bool
310 TfAnyWeakPtr::_PointerHolder<Ptr>::_IsConst() const
311 {
312  return std::is_const<typename Ptr::DataType>::value;
313 }
314 
315 PXR_NAMESPACE_CLOSE_SCOPE
316 
317 #endif
TF_API bool operator==(const TfAnyWeakPtr &rhs) const
equality operator
TF_API bool operator!() const
operator !
TF_API TfType const & GetType() const
Returns the TfType of the underlying WeakPtr.
boost::python::object TfPyObject(T const &t, bool complainOnFailure=true)
Return a python object for the given C++ object, loading the appropriate wrapper code if necessary...
Definition: pyUtils.h:102
Miscellaneous Utilities for dealing with script.
static TfType const & Find()
Retrieve the TfType corresponding to type T.
Definition: type.h:153
Pointer storage with deletion detection.
TF_API const std::type_info & GetTypeInfo() const
returns the type_info of the underlying WeakPtr
Provides the ability to hold an arbitrary TfWeakPtr in a non-type-specific manner in order to observe...
Definition: anyWeakPtr.h:54
TfAnyWeakPtr(Ptr const &ptr)
Construct an AnyWeakPtr watching ptr.
Definition: anyWeakPtr.h:67
TfAnyWeakPtr(TfNullPtrType)
Construct and implicitly convert from TfNullPtr.
Definition: anyWeakPtr.h:81
std::enable_if< std::is_polymorphic< T >::value, Tf_CopyCV< T, void > * >::type TfCastToMostDerivedType(T *ptr)
Return a pointer to the most-derived object.
Definition: cxxCast.h:67
C++ Cast Utilities.
size_t GetHash() const
Return a hash value for this instance.
Definition: anyWeakPtr.h:131
TF_API bool IsInvalid() const
Return true only if this expiry checker is watching a weak pointer which has expired.
TF_API void const * GetUniqueIdentifier() const
Return the unique identifier of the WeakPtr this AnyWeakPtr contains.
TfAnyWeakPtr()
Construct an AnyWeakPtr not watching any ptr.
Definition: anyWeakPtr.h:74
TF_API TfWeakBase const * GetWeakBase() const
Return the TfWeakBase object of the WeakPtr we are holding.
TfAnyWeakPtr(std::nullptr_t)
Construct and implicitly convert from std::nullptr_t.
Definition: anyWeakPtr.h:84
TfType represents a dynamic runtime type.
Definition: type.h:64
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
TF_API bool operator<(const TfAnyWeakPtr &rhs) const
comparison operator