All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
weakPtr.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_BASE_TF_WEAK_PTR_H
8#define PXR_BASE_TF_WEAK_PTR_H
9
13
14#include "pxr/pxr.h"
15
16#include "pxr/base/tf/nullPtr.h"
17#include "pxr/base/tf/refPtr.h"
18#include "pxr/base/tf/tf.h"
20#include "pxr/base/tf/weakPtrFacade.h"
21
22#include <cstddef>
23#include <type_traits>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
27class TfHash;
28template <class U> class TfRefPtr;
29template <class T> class TfWeakPtr;
30
126template <class T>
127class TfWeakPtr : public TfWeakPtrFacade<TfWeakPtr, T>
128{
129public:
130
131 friend class TfWeakPtrFacadeAccess;
132 template <class U> friend class TfWeakPtr;
133
134 template <class U> struct Rebind {
135 typedef TfWeakPtr<U> Type;
136 };
137
138 TfWeakPtr() : _rawPtr(0) {}
139
141 TfWeakPtr(TfNullPtrType) : _rawPtr(0) {}
142
144 TfWeakPtr(std::nullptr_t) : _rawPtr(nullptr) {}
145
147 TfWeakPtr(TfWeakPtr const &p) = default;
148
150 TfWeakPtr(TfWeakPtr &&p) noexcept
151 : _rawPtr(p._rawPtr), _remnant(std::move(p._remnant)) {
152 p._rawPtr = nullptr;
153 }
154
157 template <class U>
159 typename std::enable_if<
160 std::is_convertible<U*, T*>::value
161 >::type *dummy = 0) : _rawPtr(get_pointer(p))
162 {
163 TF_UNUSED(dummy);
164 if (ARCH_LIKELY(_rawPtr))
165 _remnant = Tf_WeakBaseAccess::
166 GetRemnant(_rawPtr->__GetTfWeakBase__());
167 }
168
170 template <class U>
171 explicit TfWeakPtr(U *p, typename std::enable_if<
172 std::is_convertible<U*, T*>::value>::type *dummy = nullptr) : _rawPtr(p)
173 {
174 TF_UNUSED(dummy);
175 if (ARCH_LIKELY(_rawPtr))
176 _remnant = Tf_WeakBaseAccess::
177 GetRemnant(_rawPtr->__GetTfWeakBase__());
178 }
179
180 template <class U>
181 TfWeakPtr(TfWeakPtr<U> const &p,
182 typename std::enable_if<
183 std::is_convertible<U*, T*>::value
184 >::type *dummy = 0) : _rawPtr(p._rawPtr), _remnant(p._remnant)
185 {
186 }
187
189 TfWeakPtr &operator=(TfWeakPtr const &p) = default;
190
193 _rawPtr = p._rawPtr;
194 _remnant = std::move(p._remnant);
195 p._rawPtr = nullptr;
196 return *this;
197 }
198
199 bool IsExpired() const {
200 return this->IsInvalid();
201 }
202
203private:
204
205 T *_FetchPointer() const {
206 if (ARCH_LIKELY(_remnant && _remnant->_IsAlive()))
207 return _rawPtr;
208 return 0;
209 }
210
211 bool _IsInvalid() const {
212 return _remnant && !_remnant->_IsAlive();
213 }
214
215 void const *_GetUniqueIdentifier() const {
216 return _remnant ? _remnant->_GetUniqueIdentifier() : 0;
217 }
218
219 void _EnableExtraNotification() const {
220 _remnant->EnableNotification();
221 }
222
223 T *_rawPtr;
224 mutable TfRefPtr<Tf_Remnant> _remnant;
225
226};
227
228
229template <class U>
230TfWeakPtr<U> TfCreateWeakPtr(U *p) {
231 return TfWeakPtr<U>(p);
232}
233
234template <class U>
235TfWeakPtr<U> TfCreateNonConstWeakPtr(U const *p) {
236 return TfWeakPtr<U>(const_cast<U *>(p));
237}
238
258template <class T>
261 typedef typename TfRefPtr<T>::_Counter Counter;
262 if (T *rawPtr = get_pointer(p)) {
263 // Atomically increment the ref-count iff it's nonzero.
264 if (Counter::AddRefIfNonzero(rawPtr)) {
265 // There was at least 1 other ref at the time we acquired our ref,
266 // so this object is safe from destruction. Transfer ownership of
267 // the ref to a new TfRefPtr.
268 return TfCreateRefPtr(rawPtr);
269 }
270 // There were 0 refs to this object, so we know it is expiring and
271 // we cannot use it.
272 }
273 return TfNullPtr;
274}
275
276
277#if !defined(doxygen)
278
279//
280// Allow TfWeakPtr<void> to be used simply for expiration checking.
281//
282template <>
283class TfWeakPtr<void> {
284public:
285 TfWeakPtr() {
286 }
287
288 template <class U>
289 TfWeakPtr(TfWeakPtr<U> const& wp)
290 : _remnant(wp._remnant) {
291 }
292
293 template <template <class> class PtrTemplate, class Type>
294 TfWeakPtr(TfWeakPtrFacade<PtrTemplate, Type> const& wpf)
295 : _remnant(_GetRemnant(wpf)) {
296 }
297
298 template <class U>
300 operator= (TfWeakPtr<U> const& wp) {
301 _remnant = wp._remnant;
302 return *this;
303 }
304
305 template <template <class> class PtrTemplate, class Type>
307 operator= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
308 _remnant = _GetRemnant(wpf);
309 return *this;
310 }
311
312 template <class U>
313 bool operator== (TfWeakPtr<U> const& wp) const {
314 return wp._remnant == _remnant;
315 }
316
317 template <template <class> class PtrTemplate, class Type>
318 bool operator== (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
319 return _GetRemnant(wpf) == _remnant;
320 }
321
322 template <class U>
323 bool operator!= (TfWeakPtr<U> const& wp) const {
324 return wp._remnant != _remnant;
325 }
326
327 template <template <class> class PtrTemplate, class Type>
328 bool operator!= (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) const {
329 return _GetRemnant(wpf) != _remnant;
330 }
331
332 template <class U>
333 bool operator< (TfWeakPtr<U> const& wp) {
334 return wp._remnant < _remnant;
335 }
336
337 template <template <class> class PtrTemplate, class Type>
338 bool operator< (TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
339 return _GetRemnant(wpf) < _remnant;
340 }
341
342 using UnspecifiedBoolType = TfRefPtr<Tf_Remnant> (TfWeakPtr::*);
343
344 operator UnspecifiedBoolType() const {
345 return (_remnant && _remnant->_IsAlive())
346 ? &TfWeakPtr::_remnant : nullptr;
347 }
348
349 bool operator !() const {
350 return !bool(*this);
351 }
352
353 bool IsExpired() const {
354 return _remnant && !_remnant->_IsAlive();
355 }
356
357private:
358 template <template <class> class PtrTemplate, class Type>
360 _GetRemnant(TfWeakPtrFacade<PtrTemplate, Type> const& wpf) {
361 TfWeakBase const *weakBase = wpf.GetWeakBase();
362 if (ARCH_LIKELY(weakBase)) {
363 return Tf_WeakBaseAccess::GetRemnant(*weakBase);
364 }
365 return TfNullPtr;
366 }
367
368private:
369 TfRefPtr<Tf_Remnant> _remnant;
370};
371
372#endif
373
374
375//
376// A mechanism to determine whether a class type has a method
377// __GetTfWeakBase__ with the correct signature.
378//
379// _HasSig can only be called with a pointer-to-member-function that matches
380// the desired signature of __GetTfWeakBase__.
381//
382// _Deduce has two possible overloads. The first overload's return value uses
383// expression SFINAE to detect if a call to _HasSig(&T::__GetTfWeakBase__) is
384// well-formed. If so, the overload's return type is the return type of
385// _HasSig, specifically std::true_type. The second _Deduce overload returns
386// std::false_type and is viable for all types.
387//
388template <class T>
389struct Tf_HasGetWeakBase
390{
391private:
392
393 // The required method signature of __GetTfWeakBase__ for implementations
394 // of the weak pointable interface.
395 template <class U>
396 using _SignatureOf__GetTfWeakBase__ = TfWeakBase const & (U::*)() const;
397
398 template <class U>
399 static std::true_type
400 _HasSig(_SignatureOf__GetTfWeakBase__<U>);
401
402 template <class U>
403 static decltype(_HasSig(&U::__GetTfWeakBase__))
404 _Deduce(U*);
405
406 static std::false_type
407 _Deduce(...);
408
409public:
410 using type = decltype(_Deduce(static_cast<T*>(nullptr)));
411 using value_type = bool;
412 static const bool value = type::value;
413};
414
415template <class T>
416struct Tf_SupportsWeakPtr
417{
418 static const bool value =
419 std::is_base_of<TfWeakBase, T>::value || Tf_HasGetWeakBase<T>::value;
420};
421
422#define TF_SUPPORTS_WEAKPTR(T) (Tf_SupportsWeakPtr<T>::value)
423#define TF_TRULY_SUPPORTS_WEAKPTR(T) std::is_base_of<TfWeakBase, T >::value
424
425#define TF_DECLARE_WEAK_POINTABLE_INTERFACE \
426 virtual TfWeakBase const &__GetTfWeakBase__() const = 0
427
428#define TF_IMPLEMENT_WEAK_POINTABLE_INTERFACE \
429 virtual TfWeakBase const &__GetTfWeakBase__() const { \
430 return *this; \
431 }
432
433PXR_NAMESPACE_CLOSE_SCOPE
434
435#endif // PXR_BASE_TF_WEAK_PTR_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:460
Reference-counted smart pointer utility class.
Definition: refPtr.h:590
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:124
This access class is befriended by TfWeakPtrFacade -derived classes to grant TfWeakPtrFacade access t...
Definition: weakPtrFacade.h:33
Pointer storage with deletion detection.
Definition: weakPtr.h:128
TfWeakPtr(std::nullptr_t)
Construction, implicit conversion from nullptr.
Definition: weakPtr.h:144
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:158
TfWeakPtr(TfWeakPtr &&p) noexcept
Move construction.
Definition: weakPtr.h:150
TfWeakPtr & operator=(TfWeakPtr const &p)=default
Copy assignment.
TfWeakPtr & operator=(TfWeakPtr &&p) noexcept
Move assignment.
Definition: weakPtr.h:192
TfWeakPtr(TfWeakPtr const &p)=default
Copy construction.
TfWeakPtr(TfNullPtrType)
Construction, implicit conversion from TfNullPtr.
Definition: weakPtr.h:141
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:171
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Definition: tf.h:168
Reference counting.
A file containing basic constants and definitions.
TfRefPtr< T > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< T > const &p)
Thread-safe creation of a Tf ref pointer from a Tf weak pointer.
Definition: weakPtr.h:260