Loading...
Searching...
No Matches
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"
37#include "pxr/base/tf/weakPtrFacade.h"
38
39#include <cstddef>
40#include <type_traits>
41
42PXR_NAMESPACE_OPEN_SCOPE
43
44class TfHash;
45template <class U> class TfRefPtr;
46template <class T> class TfWeakPtr;
47
143template <class T>
144class TfWeakPtr : public TfWeakPtrFacade<TfWeakPtr, T>
145{
146public:
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
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
220private:
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
246template <class U>
247TfWeakPtr<U> TfCreateWeakPtr(U *p) {
248 return TfWeakPtr<U>(p);
249}
250
251template <class U>
252TfWeakPtr<U> TfCreateNonConstWeakPtr(U const *p) {
253 return TfWeakPtr<U>(const_cast<U *>(p));
254}
255
275template <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//
299template <>
300class TfWeakPtr<void> {
301public:
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
374private:
375 template <template <class> class PtrTemplate, class Type>
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
385private:
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//
405template <class T>
406struct Tf_HasGetWeakBase
407{
408private:
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
426public:
427 using type = decltype(_Deduce(static_cast<T*>(nullptr)));
428 using value_type = bool;
429 static const bool value = type::value;
430};
431
432template <class T>
433struct 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
450PXR_NAMESPACE_CLOSE_SCOPE
451
452#endif // PXR_BASE_TF_WEAK_PTR_H
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:477
Reference-counted smart pointer utility class.
Definition: refPtr.h:601
Enable a concrete base class for use with TfWeakPtr.
Definition: weakBase.h:141
This access class is befriended by TfWeakPtrFacade -derived classes to grant TfWeakPtrFacade access t...
Definition: weakPtrFacade.h:50
Pointer storage with deletion detection.
Definition: weakPtr.h:145
TfWeakPtr(std::nullptr_t)
Construction, implicit conversion from nullptr.
Definition: weakPtr.h:161
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
TfWeakPtr(TfWeakPtr &&p) noexcept
Move construction.
Definition: weakPtr.h:167
TfWeakPtr & operator=(TfWeakPtr const &p)=default
Copy assignment.
TfWeakPtr & operator=(TfWeakPtr &&p) noexcept
Move assignment.
Definition: weakPtr.h:209
TfWeakPtr(TfWeakPtr const &p)=default
Copy construction.
TfWeakPtr(TfNullPtrType)
Construction, implicit conversion from TfNullPtr.
Definition: weakPtr.h:158
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
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:277