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 
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) = default;
165 
167  TfWeakPtr(TfWeakPtr &&p) noexcept
168  : _rawPtr(p._rawPtr), _remnant(std::move(p._remnant)) {
169  p._rawPtr = nullptr;
170  }
171 
174  template <class U>
176  typename std::enable_if<
177  std::is_convertible<U*, T*>::value
178  >::type *dummy = 0) : _rawPtr(get_pointer(p))
179  {
180  TF_UNUSED(dummy);
181  if (ARCH_LIKELY(_rawPtr))
182  _remnant = Tf_WeakBaseAccess::
183  GetRemnant(_rawPtr->__GetTfWeakBase__());
184  }
185 
187  template <class U>
188  explicit TfWeakPtr(U *p, typename std::enable_if<
189  std::is_convertible<U*, T*>::value>::type *dummy = nullptr) : _rawPtr(p)
190  {
191  TF_UNUSED(dummy);
192  if (ARCH_LIKELY(_rawPtr))
193  _remnant = Tf_WeakBaseAccess::
194  GetRemnant(_rawPtr->__GetTfWeakBase__());
195  }
196 
197  template <class U>
198  TfWeakPtr(TfWeakPtr<U> const &p,
199  typename std::enable_if<
200  std::is_convertible<U*, T*>::value
201  >::type *dummy = 0) : _rawPtr(p._rawPtr), _remnant(p._remnant)
202  {
203  }
204 
206  TfWeakPtr &operator=(TfWeakPtr const &p) = default;
207 
209  TfWeakPtr &operator=(TfWeakPtr &&p) noexcept {
210  _rawPtr = p._rawPtr;
211  _remnant = std::move(p._remnant);
212  p._rawPtr = nullptr;
213  return *this;
214  }
215 
216  bool IsExpired() const {
217  return this->IsInvalid();
218  }
219 
220 private:
221 
222  T *_FetchPointer() const {
223  if (ARCH_LIKELY(_remnant && _remnant->_IsAlive()))
224  return _rawPtr;
225  return 0;
226  }
227 
228  bool _IsInvalid() const {
229  return _remnant && !_remnant->_IsAlive();
230  }
231 
232  void const *_GetUniqueIdentifier() const {
233  return _remnant ? _remnant->_GetUniqueIdentifier() : 0;
234  }
235 
236  void _EnableExtraNotification() const {
237  _remnant->EnableNotification();
238  }
239 
240  T *_rawPtr;
241  mutable TfRefPtr<Tf_Remnant> _remnant;
242 
243 };
244 
245 
246 template <class U>
247 TfWeakPtr<U> TfCreateWeakPtr(U *p) {
248  return TfWeakPtr<U>(p);
249 }
250 
251 template <class U>
252 TfWeakPtr<U> TfCreateNonConstWeakPtr(U const *p) {
253  return TfWeakPtr<U>(const_cast<U *>(p));
254 }
255 
275 template <class T>
278  typedef typename TfRefPtr<T>::_Counter Counter;
279  if (T *rawPtr = get_pointer(p)) {
280  // Atomically increment the ref-count iff it's nonzero.
281  if (Counter::AddRefIfNonzero(rawPtr)) {
282  // There was at least 1 other ref at the time we acquired our ref,
283  // so this object is safe from destruction. Transfer ownership of
284  // the ref to a new TfRefPtr.
285  return TfCreateRefPtr(rawPtr);
286  }
287  // There were 0 refs to this object, so we know it is expiring and
288  // we cannot use it.
289  }
290  return TfNullPtr;
291 }
292 
293 
294 #if !defined(doxygen)
295 
296 //
297 // Allow TfWeakPtr<void> to be used simply for expiration checking.
298 //
299 template <>
300 class TfWeakPtr<void> {
301 public:
302  TfWeakPtr() {
303  }
304 
305  template <class U>
306  TfWeakPtr(TfWeakPtr<U> const& wp)
307  : _remnant(wp._remnant) {
308  }
309 
310  template <template <class> class PtrTemplate, class Type>
311  TfWeakPtr(TfWeakPtrFacade<PtrTemplate, Type> const& wpf)
312  : _remnant(_GetRemnant(wpf)) {
313  }
314 
315  template <class U>
317  operator= (TfWeakPtr<U> const& wp) {
318  _remnant = wp._remnant;
319  return *this;
320  }
321 
322  template <template <class> class PtrTemplate, class Type>
324  operator= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
325  _remnant = _GetRemnant(wpf);
326  return *this;
327  }
328 
329  template <class U>
330  bool operator== (TfWeakPtr<U> const& wp) const {
331  return wp._remnant == _remnant;
332  }
333 
334  template <template <class> class PtrTemplate, class Type>
335  bool operator== (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
336  return _GetRemnant(wpf) == _remnant;
337  }
338 
339  template <class U>
340  bool operator!= (TfWeakPtr<U> const& wp) const {
341  return wp._remnant != _remnant;
342  }
343 
344  template <template <class> class PtrTemplate, class Type>
345  bool operator!= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
346  return _GetRemnant(wpf) != _remnant;
347  }
348 
349  template <class U>
350  bool operator< (TfWeakPtr<U> const& wp) {
351  return wp._remnant < _remnant;
352  }
353 
354  template <template <class> class PtrTemplate, class Type>
355  bool operator< (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
356  return _GetRemnant(wpf) < _remnant;
357  }
358 
359  using UnspecifiedBoolType = TfRefPtr<Tf_Remnant> (TfWeakPtr::*);
360 
361  operator UnspecifiedBoolType() const {
362  return (_remnant && _remnant->_IsAlive())
363  ? &TfWeakPtr::_remnant : nullptr;
364  }
365 
366  bool operator !() const {
367  return !bool(*this);
368  }
369 
370  bool IsExpired() const {
371  return _remnant && !_remnant->_IsAlive();
372  }
373 
374 private:
375  template <template <class> class PtrTemplate, class Type>
376  static TfRefPtr<Tf_Remnant>
377  _GetRemnant(TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
378  TfWeakBase const *weakBase = wpf.GetWeakBase();
379  if (ARCH_LIKELY(weakBase)) {
380  return Tf_WeakBaseAccess::GetRemnant(*weakBase);
381  }
382  return TfNullPtr;
383  }
384 
385 private:
386  TfRefPtr<Tf_Remnant> _remnant;
387 };
388 
389 #endif
390 
391 
392 //
393 // A mechanism to determine whether a class type has a method
394 // __GetTfWeakBase__ with the correct signature.
395 //
396 // _HasSig can only be called with a pointer-to-member-function that matches
397 // the desired signature of __GetTfWeakBase__.
398 //
399 // _Deduce has two possible overloads. The first overload's return value uses
400 // expression SFINAE to detect if a call to _HasSig(&T::__GetTfWeakBase__) is
401 // well-formed. If so, the overload's return type is the return type of
402 // _HasSig, specifically std::true_type. The second _Deduce overload returns
403 // std::false_type and is viable for all types.
404 //
405 template <class T>
406 struct Tf_HasGetWeakBase
407 {
408 private:
409 
410  // The required method signature of __GetTfWeakBase__ for implementations
411  // of the weak pointable interface.
412  template <class U>
413  using _SignatureOf__GetTfWeakBase__ = TfWeakBase const & (U::*)() const;
414 
415  template <class U>
416  static std::true_type
417  _HasSig(_SignatureOf__GetTfWeakBase__<U>);
418 
419  template <class U>
420  static decltype(_HasSig(&U::__GetTfWeakBase__))
421  _Deduce(U*);
422 
423  static std::false_type
424  _Deduce(...);
425 
426 public:
427  using type = decltype(_Deduce(static_cast<T*>(nullptr)));
428  using value_type = bool;
429  static const bool value = type::value;
430 };
431 
432 template <class T>
433 struct Tf_SupportsWeakPtr
434 {
435  static const bool value =
436  std::is_base_of<TfWeakBase, T>::value || Tf_HasGetWeakBase<T>::value;
437 };
438 
439 #define TF_SUPPORTS_WEAKPTR(T) (Tf_SupportsWeakPtr<T>::value)
440 #define TF_TRULY_SUPPORTS_WEAKPTR(T) std::is_base_of<TfWeakBase, T >::value
441 
442 #define TF_DECLARE_WEAK_POINTABLE_INTERFACE \
443  virtual TfWeakBase const &__GetTfWeakBase__() const = 0
444 
445 #define TF_IMPLEMENT_WEAK_POINTABLE_INTERFACE \
446  virtual TfWeakBase const &__GetTfWeakBase__() const { \
447  return *this; \
448  }
449 
450 PXR_NAMESPACE_CLOSE_SCOPE
451 
452 #endif // PXR_BASE_TF_WEAK_PTR_H
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:277
TfWeakPtr & operator=(TfWeakPtr const &p)=default
Copy assignment.
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:188
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition: tf.h:185
Pointer storage with deletion detection.
Definition: refBase.h:38
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:447
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:53
TfWeakPtr(TfWeakPtr &&p) noexcept
Move construction.
Definition: weakPtr.h:167
TfWeakPtr & operator=(TfWeakPtr &&p) noexcept
Move assignment.
Definition: weakPtr.h:209
Reference counting.
TfWeakPtr(TfNullPtrType)
Construction, implicit conversion from TfNullPtr.
Definition: weakPtr.h:158
Reference-counted smart pointer utility class.
Definition: refBase.h:37
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
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:175
A file containing basic constants and definitions.