HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
weakPtr.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_WEAK_PTR_H
25 #define PXR_BASE_TF_WEAK_PTR_H
26 
27 /// \file tf/weakPtr.h
28 /// \ingroup group_tf_Memory
29 /// Pointer storage with deletion detection.
30 
31 #include "pxr/pxr.h"
32 
33 #include "pxr/base/tf/nullPtr.h"
34 #include "pxr/base/tf/refPtr.h"
35 #include "pxr/base/tf/tf.h"
36 #include "pxr/base/tf/weakBase.h"
38 
39 #include <cstddef>
40 #include <type_traits>
41 
43 
44 class TfHash;
45 template <class U> class TfRefPtr;
46 template <class T> class TfWeakPtr;
47 
48 /// \class TfWeakPtr
49 /// \ingroup group_tf_Memory
50 ///
51 /// Pointer storage with deletion detection.
52 ///
53 /// <b>Overview</b>
54 ///
55 /// A \c TfWeakPtr is used to cache a pointer to an object; before
56 /// retrieving/using this pointer, one queries the \c TfWeakPtr object to
57 /// verify that the objected pointed to has not been deleted in the interim.
58 ///
59 /// \include test/weakPtr.cpp
60 ///
61 /// In the code above, if \c PossiblyDeleteLemur() deletes the object pointed
62 /// to by \c lemur, then the test \c if(lPtr) returns false. Otherwise, it is
63 /// safe to call a method on \c lPtr.
64 ///
65 /// To declare a \c TfWeakPtr<T>, the type \c T must publicly derive from \c
66 /// TfWeakBase.
67 ///
68 /// <b>Basic Use</b>
69 ///
70 /// A \c TfWeakPtr<T> can access \c T's public members by the \c -> operator
71 /// and can be dereferenced by the "\c *" operator.
72 ///
73 /// A \c TfWeakPtr converts to a \c true bool value (for example, in an \c if
74 /// statement) only if the pointer points to an unexpired object. Otherwise,
75 /// if the pointer was either initialized to NULL, or points to an expired
76 /// object, the test returns false.
77 ///
78 /// Occasionally, it is useful to distinguish between a \c TfWeakPtr being
79 /// explicitly initialized to NULL versus a \c TfWeakPtr whose object has
80 /// expired: the member function \c IsInvalid() returns \c true only if the
81 /// pointer points to an expired object.
82 ///
83 /// <b>Opaqueness</b>
84 ///
85 /// See the parallel discussion about these concepts in the documentation for
86 /// \c TfRefPtr; the same concepts apply.
87 ///
88 /// <b>Comparisons, Const and Non-Const, Inheritance and Casting</b>
89 ///
90 /// See the parallel discussion about these concepts in the documentation for
91 /// \c TfRefPtr; the same concepts apply.
92 ///
93 /// While it is possible to create TfWeakPtrs to const contents, we recommend
94 /// against it. TfCreateNonConstWeakPtr will always create a non-const weak
95 /// pointer even when passed a const argument (it casts away const).
96 ///
97 /// The recommendation against use of weak pointers to const content is due to
98 /// the fact that weak pointers cannot be implicitly cast for both inheritance
99 /// (derived to base) and const-ness (non-const to const) at the same time.
100 /// Because of this, using weak pointers to const content is most often much
101 /// more trouble than the benefit it gives. Therefore our policy is to not
102 /// use them.
103 ///
104 /// <b>Pointer Generality</b>
105 ///
106 /// While \c TfWeakPtr<TfWeakBase> is specifically forbidden (you cannot
107 /// construct this kind of object), you can assign any \c TfWeakPtr<T> to a \c
108 /// TfWeakPtr<void> or TfWeakPtr<const void>. The only thing you can do with
109 /// the latter is check to see if it points to an object that has expired.
110 /// You cannot manipulate the object itself (i.e. access its member
111 /// functions).
112 ///
113 /// This is useful when you need to watch for object expiration without being
114 /// bound by the type(s) of the objects you're watching. Similarly, you can
115 /// create a TfWeakPtr<void> from a \c TfWeakBase * using \c
116 /// TfCreateWeakPtr().
117 ///
118 /// <b>Performance</b>
119 ///
120 /// Deriving from \c TfWeakBase results in a single \c TfRefPtr variable being
121 /// added to a class, which is the size of a regular pointer. The cost of
122 /// deleting an object derived from \c TfWeakBase is an extra inline boolean
123 /// comparison, and possible decrement of a reference count if the object's
124 /// address was ever given out as a \c TfWeakPtr.
125 ///
126 /// The cost to create a \c TfWeakPtr is as follows: initial creation of the
127 /// pointer from a \c TfWeakBase object dynamically creates an object called a
128 /// \e remnant, whose size is that of two pointers. Subsequent transfers of
129 /// the same object's address to another \c TfWeakPtr merely bump a reference
130 /// count to the remnant. When all \c TfWeakPtrs to the object (and the object
131 /// itself) are destroyed, the remnant is deleted. An object can have a
132 /// remnant created and destroyed at most once, regardless of how many times
133 /// its address is given out in the form of a \c TfWeakPtr.
134 ///
135 /// Summarizing, the cost of guarding an object is a small amount of extra
136 /// space, and near-zero runtime cost if the guarding is never used. Even if
137 /// the guarding is used, the overhead at deletion time is minimal.
138 ///
139 /// The time to test if a \c TfWeakPtr is NULL, or to call a member function
140 /// through a \c TfWeakPtr is small, involving only a single inline boolean
141 /// comparison.
142 ///
143 template <class T>
144 class TfWeakPtr : public TfWeakPtrFacade<TfWeakPtr, T>
145 {
146 public:
147 
148  friend class TfWeakPtrFacadeAccess;
149  template <class U> friend class TfWeakPtr;
150 
151  template <class U> struct Rebind {
153  };
154 
155  TfWeakPtr() : _rawPtr(0) {}
156 
157  /// Construction, implicit conversion from TfNullPtr.
158  TfWeakPtr(TfNullPtrType) : _rawPtr(0) {}
159 
160  /// Construction, implicit conversion from nullptr.
161  TfWeakPtr(std::nullptr_t) : _rawPtr(nullptr) {}
162 
163  /// Copy construction
164  TfWeakPtr(TfWeakPtr const &p) : _rawPtr(p._rawPtr), _remnant(p._remnant)
165  {
166  }
167 
168  /// Conversion from \a RefPtr where \a U* is convertible to \a T* (this
169  /// pointer type).
170  template <class U>
172  typename std::enable_if<
174  >::type *dummy = 0) : _rawPtr(get_pointer(p))
175  {
176  TF_UNUSED(dummy);
177  if (ARCH_LIKELY(_rawPtr))
178  _remnant = Tf_WeakBaseAccess::
179  GetRemnant(_rawPtr->__GetTfWeakBase__());
180  }
181 
182  /// Explicitly construct from a raw pointer \a p.
183  template <class U>
184  explicit TfWeakPtr(U *p, typename std::enable_if<
185  std::is_convertible<U*, T*>::value>::type *dummy = nullptr) : _rawPtr(p)
186  {
187  TF_UNUSED(dummy);
188  if (ARCH_LIKELY(_rawPtr))
189  _remnant = Tf_WeakBaseAccess::
190  GetRemnant(_rawPtr->__GetTfWeakBase__());
191  }
192 
193  template <class U>
195  typename std::enable_if<
197  >::type *dummy = 0) : _rawPtr(p._rawPtr), _remnant(p._remnant)
198  {
199  }
200 
201  bool IsExpired() const {
202  return this->IsInvalid();
203  }
204 
205 private:
206 
207  T *_FetchPointer() const {
208  if (ARCH_LIKELY(_remnant && _remnant->_IsAlive()))
209  return _rawPtr;
210  return 0;
211  }
212 
213  bool _IsInvalid() const {
214  return _remnant && !_remnant->_IsAlive();
215  }
216 
217  void const *_GetUniqueIdentifier() const {
218  return _remnant ? _remnant->_GetUniqueIdentifier() : 0;
219  }
220 
221  void _EnableExtraNotification() const {
222  _remnant->EnableNotification();
223  }
224 
225  T *_rawPtr;
226  mutable TfRefPtr<Tf_Remnant> _remnant;
227 
228 };
229 
230 
231 template <class U>
233  return TfWeakPtr<U>(p);
234 }
235 
236 template <class U>
238  return TfWeakPtr<U>(const_cast<U *>(p));
239 }
240 
241 /// Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
242 ///
243 /// This is thread-safe in the sense that the result will be either a ref
244 /// pointer to a live object with non-zero ref-count, or a NULL ref pointer.
245 /// However, this depends on the client to provide a guarantee to protect the
246 /// pointed-to object.
247 ///
248 /// Specifically, the caller must guarantee that the TfRefBase part of the
249 /// pointed-to object is not destroyed during this call. It is fine if the
250 /// destruction process for the object begins (due to the ref-count going to
251 /// zero as another thread drops the last ref) as long as the TfRefBase
252 /// portion is not destroyed. If object destruction begins because the
253 /// ref-count goes to zero before this call completes, this function will
254 /// reliably return a NULL ref pointer.
255 ///
256 /// Note that this is not a general mechanism for safely converting weak
257 /// pointers to ref pointers, because it relies on the type T to provide the
258 /// above guarantee.
259 ///
260 template <class T>
263  typedef typename TfRefPtr<T>::_Counter Counter;
264  if (T *rawPtr = get_pointer(p)) {
265  // Atomically increment the ref-count iff it's nonzero.
266  if (Counter::AddRefIfNonzero(rawPtr)) {
267  // There was at least 1 other ref at the time we acquired our ref,
268  // so this object is safe from destruction. Transfer ownership of
269  // the ref to a new TfRefPtr.
270  return TfCreateRefPtr(rawPtr);
271  }
272  // There were 0 refs to this object, so we know it is expiring and
273  // we cannot use it.
274  }
275  return TfNullPtr;
276 }
277 
278 
279 #if !defined(doxygen)
280 
281 //
282 // Allow TfWeakPtr<void> to be used simply for expiration checking.
283 //
284 template <>
285 class TfWeakPtr<void> {
286 public:
288  }
289 
290  template <class U>
292  : _remnant(wp._remnant) {
293  }
294 
295  template <template <class> class PtrTemplate, class Type>
297  : _remnant(_GetRemnant(wpf)) {
298  }
299 
300  template <class U>
302  operator= (TfWeakPtr<U> const& wp) {
303  _remnant = wp._remnant;
304  return *this;
305  }
306 
307  template <template <class> class PtrTemplate, class Type>
309  operator= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
310  _remnant = _GetRemnant(wpf);
311  return *this;
312  }
313 
314  template <class U>
315  bool operator== (TfWeakPtr<U> const& wp) const {
316  return wp._remnant == _remnant;
317  }
318 
319  template <template <class> class PtrTemplate, class Type>
321  return _GetRemnant(wpf) == _remnant;
322  }
323 
324  template <class U>
325  bool operator!= (TfWeakPtr<U> const& wp) const {
326  return wp._remnant != _remnant;
327  }
328 
329  template <template <class> class PtrTemplate, class Type>
331  return _GetRemnant(wpf) != _remnant;
332  }
333 
334  template <class U>
335  bool operator< (TfWeakPtr<U> const& wp) {
336  return wp._remnant < _remnant;
337  }
338 
339  template <template <class> class PtrTemplate, class Type>
340  bool operator< (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
341  return _GetRemnant(wpf) < _remnant;
342  }
343 
345 
346  operator UnspecifiedBoolType() const {
347  return (_remnant && _remnant->_IsAlive())
348  ? &TfWeakPtr::_remnant : nullptr;
349  }
350 
351  bool operator !() const {
352  return !bool(*this);
353  }
354 
355  bool IsExpired() const {
356  return _remnant && !_remnant->_IsAlive();
357  }
358 
359 private:
360  template <template <class> class PtrTemplate, class Type>
361  static TfRefPtr<Tf_Remnant>
362  _GetRemnant(TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
363  TfWeakBase const *weakBase = wpf.GetWeakBase();
364  if (ARCH_LIKELY(weakBase)) {
365  return Tf_WeakBaseAccess::GetRemnant(*weakBase);
366  }
367  return TfNullPtr;
368  }
369 
370 private:
371  TfRefPtr<Tf_Remnant> _remnant;
372 };
373 
374 #endif
375 
376 
377 //
378 // A mechanism to determine whether a class type has a method
379 // __GetTfWeakBase__ with the correct signature.
380 //
381 // _HasSig can only be called with a pointer-to-member-function that matches
382 // the desired signature of __GetTfWeakBase__.
383 //
384 // _Deduce has two possible overloads. The first overload's return value uses
385 // expression SFINAE to detect if a call to _HasSig(&T::__GetTfWeakBase__) is
386 // well-formed. If so, the overload's return type is the return type of
387 // _HasSig, specifically std::true_type. The second _Deduce overload returns
388 // std::false_type and is viable for all types.
389 //
390 template <class T>
392 {
393 private:
394 
395  // The required method signature of __GetTfWeakBase__ for implementations
396  // of the weak pointable interface.
397  template <class U>
398  using _SignatureOf__GetTfWeakBase__ = TfWeakBase const & (U::*)() const;
399 
400  template <class U>
401  static std::true_type
402  _HasSig(_SignatureOf__GetTfWeakBase__<U>);
403 
404  template <class U>
405  static decltype(_HasSig(&U::__GetTfWeakBase__))
406  _Deduce(U*);
407 
408  static std::false_type
409  _Deduce(...);
410 
411 public:
412  using type = decltype(_Deduce(static_cast<T*>(nullptr)));
413  using value_type = bool;
414  static const bool value = type::value;
415 };
416 
417 template <class T>
419 {
420  static const bool value =
422 };
423 
424 #define TF_SUPPORTS_WEAKPTR(T) (Tf_SupportsWeakPtr<T>::value)
425 #define TF_TRULY_SUPPORTS_WEAKPTR(T) std::is_base_of<TfWeakBase, T >::value
426 
427 #define TF_DECLARE_WEAK_POINTABLE_INTERFACE \
428  virtual TfWeakBase const &__GetTfWeakBase__() const = 0
429 
430 #define TF_IMPLEMENT_WEAK_POINTABLE_INTERFACE \
431  virtual TfWeakBase const &__GetTfWeakBase__() const { \
432  return *this; \
433  }
434 
436 
437 #endif // PXR_BASE_TF_WEAK_PTR_H
#define ARCH_LIKELY(x)
Definition: hints.h:46
TfRefPtr< T > TfCreateRefPtr(T *ptr)
Definition: refPtr.h:1248
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Definition: weakPtr.h:262
TfRefPtr< Tf_Remnant >(TfWeakPtr::*) UnspecifiedBoolType
Definition: weakPtr.h:344
bool operator==(PtrTemplate< Other > const &p) const
bool operator!=(PtrTemplate< Other > const &p) const
decltype(_Deduce(static_cast< T * >(nullptr))) type
Definition: weakPtr.h:412
TF_API const TfNullPtrType TfNullPtr
TfWeakPtr(TfWeakPtrFacade< PtrTemplate, Type > const &wpf)
Definition: weakPtr.h:296
static TfRefPtr< Tf_Remnant > GetRemnant(TfWeakBase const &wb)
Definition: weakBase.h:212
TfWeakPtr(std::nullptr_t)
Construction, implicit conversion from nullptr.
Definition: weakPtr.h:161
TfWeakPtr()
Definition: weakPtr.h:155
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:86
Definition: hash.h:366
DataType *(TfWeakPtrFacade::*)(void) const UnspecifiedBoolType
TfWeakPtr< U > Type
Definition: weakPtr.h:152
TfWeakPtr< U > TfCreateNonConstWeakPtr(U const *p)
Definition: weakPtr.h:237
TfWeakPtr(TfRefPtr< U > const &p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=0)
Definition: weakPtr.h:171
void
Definition: png.h:1083
bool IsExpired() const
Definition: weakPtr.h:355
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
virtual TF_API void const * _GetUniqueIdentifier() const
GLfloat GLfloat p
Definition: glew.h:16321
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1346
bool IsExpired() const
Definition: weakPtr.h:201
#define TF_UNUSED(x)
Definition: tf.h:185
TfWeakPtr(TfWeakPtr const &p)
Copy construction.
Definition: weakPtr.h:164
bool _IsAlive() const
Definition: weakBase.h:58
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
TfWeakPtr(U *p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=nullptr)
Explicitly construct from a raw pointer p.
Definition: weakPtr.h:184
TfWeakPtr(TfNullPtrType)
Construction, implicit conversion from TfNullPtr.
Definition: weakPtr.h:158
TfWeakPtr(TfWeakPtr< U > const &p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=0)
Definition: weakPtr.h:194
GLsizei const GLfloat * value
Definition: glew.h:1849
TfWeakBase const * GetWeakBase() const
virtual TF_API void EnableNotification() const
TfWeakPtr< U > TfCreateWeakPtr(U *p)
Definition: weakPtr.h:232
TfWeakPtr(TfWeakPtr< U > const &wp)
Definition: weakPtr.h:291