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 TF_WEAKPTR_H
25 #define TF_WEAKPTR_H
26 
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"
37 #include "pxr/base/tf/weakPtrFacade.h"
38 
39 #include <cstddef>
40 #include <type_traits>
41 
42 PXR_NAMESPACE_OPEN_SCOPE
43 
44 class TfHash;
45 template <class U> class TfRefPtr;
46 template <class T> class TfWeakPtr;
47 
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 {
152  typedef TfWeakPtr<U> Type;
153  };
154 
155  TfWeakPtr() : _rawPtr(0) {}
156 
158  TfWeakPtr(TfNullPtrType) : _rawPtr(0) {}
159 
161  TfWeakPtr(std::nullptr_t) : _rawPtr(nullptr) {}
162 
164  TfWeakPtr(TfWeakPtr const &p) : _rawPtr(p._rawPtr), _remnant(p._remnant)
165  {
166  }
167 
170  template <class U>
172  typename std::enable_if<
173  std::is_convertible<U*, T*>::value
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 
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>
194  TfWeakPtr(TfWeakPtr<U> const &p,
195  typename std::enable_if<
196  std::is_convertible<U*, T*>::value
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>
232 TfWeakPtr<U> TfCreateWeakPtr(U *p) {
233  return TfWeakPtr<U>(p);
234 }
235 
236 template <class U>
237 TfWeakPtr<U> TfCreateNonConstWeakPtr(U const *p) {
238  return TfWeakPtr<U>(const_cast<U *>(p));
239 }
240 
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:
287  TfWeakPtr() {
288  }
289 
290  template <class U>
291  TfWeakPtr(TfWeakPtr<U> const& wp)
292  : _remnant(wp._remnant) {
293  }
294 
295  template <template <class> class PtrTemplate, class Type>
296  TfWeakPtr(TfWeakPtrFacade<PtrTemplate, Type> const& wpf)
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>
320  bool operator== (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
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>
330  bool operator!= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
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 
344  using UnspecifiedBoolType = TfRefPtr<Tf_Remnant> (TfWeakPtr::*);
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>
391 struct Tf_HasGetWeakBase
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>
418 struct Tf_SupportsWeakPtr
419 {
420  static const bool value =
421  std::is_base_of<TfWeakBase, T>::value || Tf_HasGetWeakBase<T>::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 
435 PXR_NAMESPACE_CLOSE_SCOPE
436 
437 #endif // TF_WEAKPTR_H
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:262
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(TfWeakPtr const &p)
Copy construction.
Definition: weakPtr.h:164
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition: tf.h:185
Pointer storage with deletion detection.
Definition: hash.h:44
Provides hash function on STL string types and other types.
Definition: hash.h:86
TfWeakPtr(std::nullptr_t)
Construction, implicit conversion from nullptr.
Definition: weakPtr.h:161
This access class is befriended by TfWeakPtrFacade -derived classes to grant TfWeakPtrFacade access t...
Definition: weakPtrFacade.h:54
TfWeakPtr(TfNullPtrType)
Construction, implicit conversion from TfNullPtr.
Definition: weakPtr.h:158
Reference-counted smart pointer utility class.
Definition: hash.h:45
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:142
TfWeakPtr(TfRefPtr< U > const &p, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *dummy=0)
Conversion from RefPtr where U* is convertible to T* (this pointer type).
Definition: weakPtr.h:171