HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
refPtr.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_REF_PTR_H
8 #define PXR_BASE_TF_REF_PTR_H
9 
10 /// \file tf/refPtr.h
11 /// \ingroup group_tf_Memory
12 /// Reference counting.
13 ///
14 /// \anchor refPtr_QuickStart
15 /// <B> Quick Start </B>
16 ///
17 /// Here is how to make a class \c Bunny usable through \c TfRefPtr.
18 ///
19 /// \code
20 /// #include "pxr/base/tf/refPtr.h"
21 /// typedef TfRefPtr<Bunny> BunnyRefPtr;
22 ///
23 /// class Bunny : public TfRefBase {
24 /// public:
25 /// static BunnyRefPtr New() {
26 /// // warning: return new Bunny directly will leak memory!
27 /// return TfCreateRefPtr(new Bunny);
28 /// }
29 /// static BunnyRefPtr New(bool isRabid) {
30 /// return TfCreateRefPtr(new Bunny(isRabid));
31 /// }
32 ///
33 /// ~Bunny();
34 ///
35 /// bool IsHungry();
36 /// private:
37 /// Bunny();
38 /// Bunny(bool);
39 /// };
40 ///
41 /// BunnyRefPtr nice = Bunny::New();
42 /// BunnyRefPtr mean = Bunny::New(true); // this one is rabid
43 ///
44 /// BunnyRefPtr mean2 = mean; // two references to mean rabbit
45 /// mean.Reset(); // one reference to mean rabbit
46 ///
47 /// if (mean2->IsHungry())
48 /// nice.Reset(); // nice bunny gone now...
49 ///
50 /// // this function comes from
51 /// // TfRefBase; meaning is that
52 /// if (mean2->IsUnique()) // mean2 is the last pointer to
53 /// mean2.Reset(); // this bunny...
54 /// \endcode
55 ///
56 /// Pretty much any pointer operation that is legal with regular pointers
57 /// is legal with the \c BunnyRefPtr; continue reading for a more detailed
58 /// description.
59 ///
60 /// Note that by virtue of deriving from \c TfRefBase, the reference
61 /// count can be queried: see \c TfRefBase for details.
62 ///
63 /// \anchor refPtr_DetailedDiscussion
64 /// <B> Detailed Discussion: Overview </B>
65 ///
66 /// Objects created by the \c new operator can easily be a source of
67 /// both memory leaks and dangling pointers. One solution is
68 /// \e reference counting; when an object is created by \c new,
69 /// the number of pointers given the object's address is continually
70 /// tracked in a \e reference \e counter. Then, \c delete is called on
71 /// the object \e only when the object's reference count drops to zero,
72 /// meaning there are no more pointers left pointing to the object.
73 /// Reference counting avoids both dangling pointers and memory leaks.
74 ///
75 /// Access by regular pointers does not perform reference counting, but
76 /// the \c TfRefPtr<T> class implements reference-counted pointer access
77 /// to objects of type \c T, with minimal overhead. The reference counting
78 /// is made thread-safe by use of atomic integers.
79 ///
80 ///
81 /// <B> Basic Use </B>
82 ///
83 /// The use of a \c TfRefPtr is simple. Whenever a \c TfRefPtr is
84 /// made to point at an object, either by initialization or assignment,
85 /// the object being pointed at has its reference count incremented.
86 /// When a \c TfRefPtr with a non-NULL address is reassigned, or
87 /// goes out of scope, the object being pointed to has its reference
88 /// count decremented.
89 ///
90 /// A \c TfRefPtr<T> can access \c T's public members by the
91 /// \c -> operator and can be dereferenced by the "\c *" operator.
92 /// Here is a simple example:
93 /// \code
94 /// #include "pxr/base/tf/refPtr.h"
95 ///
96 /// typedef TfRefPtr<Simple> SimpleRefPtr;
97 ///
98 /// class Simple : public TfRefBase {
99 /// public:
100 /// void Method1();
101 /// int Method2();
102 ///
103 /// static SimpleRefPtr New() {
104 /// return TfCreateRefPtr(new Simple);
105 /// }
106 /// private:
107 /// Simple();
108 /// };
109 ///
110 ///
111 /// SimpleRefPtr p1; // p1 points to NULL
112 /// SimpleRefPtr p2 = Simple::New(); // p2 points to new object A
113 /// SimpleRefPtr p3 = Simple::New(); // p3 points to new object B
114 ///
115 /// p1->Method1(); // runtime error -- p1 is NULL
116 /// p3 = p2; // object B is deleted
117 /// p2->Method1(); // Method1 on object A
118 /// int value = p3->Method2(); // Method2 on object A
119 ///
120 /// p2.Reset(); // only p3 still points at A
121 /// p3 = p1; // object A is deleted
122 ///
123 /// if (...) {
124 /// SimpleRefPtr p4 = Simple::New(); // p4 points to object C
125 /// p4->Method1();
126 /// } // object C destroyed
127 /// \endcode
128 ///
129 /// Note that \c Simple's constructor is private; this ensures that one
130 /// can only get at a \c Simple through \c Simple::New(), which is careful
131 /// to return a \c SimpleRefPtr.
132 ///
133 /// Note that it is often useful to have both const and non-const
134 /// versions of \c TfRefPtr for the same data type. Our convention
135 /// is to use a \c typedef for each of these, with the const version
136 /// beginning with "Const", after any prefix. The const version can be
137 /// used as a parameter to a function in which you want to prevent
138 /// changes to the pointed-to object. For example:
139 /// \code
140 /// typedef TfRefPtr<XySimple> XySimpleRefPtr;
141 /// typedef TfRefPtr<const XySimple> XyConstSimpleRefPtr;
142 ///
143 /// void
144 /// Func1(const XySimpleRefPtr &p)
145 /// {
146 /// p->Modify(); // OK even if Modify() is not a const member
147 /// }
148 ///
149 /// void
150 /// Func2(const XyConstSimpleRefPtr &p)
151 /// {
152 /// p->Query(); // OK only if Query() is a const member
153 /// }
154 /// \endcode
155 ///
156 /// It is always possible to assign a non-const pointer to a const
157 /// pointer variable. In extremely rare cases where you want to do the
158 /// opposite, you can use the \c TfConst_cast function, as in:
159 /// \code
160 /// XyConstSimpleRefPtr p1;
161 /// XySimpleRefPtr p2;
162 ///
163 /// p1 = p2; // OK
164 /// p2 = p1; // Illegal!
165 /// p2 = TfConst_cast<XySimpleRefPtr>(p1); // OK, but discouraged
166 /// \endcode
167 ///
168 /// <B> Comparisons and Tests </B>
169 ///
170 /// Reference-counted pointers of like type can be compared; any \c TfRefPtr
171 /// can be tested to see it is NULL or not:
172 ///
173 /// \code
174 /// TfRefPtr<Elf> elf = Elf::New();
175 /// TfRefPtr<Dwarf> sleepy,
176 /// sneezy = Dwarf::New();
177 ///
178 /// if (!sleepy)
179 /// ... // true: sleepy is NULL
180 ///
181 /// if (sneezy)
182 /// ... // true: sneezy is non-nULL
183 ///
184 /// bool b1 = (sleepy != sneezy),
185 /// b2 = (sleepy == sneezy),
186 /// b3 = (elf == sneezy); // compilation error -- type clash
187 ///
188 /// \endcode
189 ///
190 /// <B> Opaqueness </B>
191 ///
192 /// A \c TfRefPtr can be used as an opaque pointer, just as a regular
193 /// pointer can. For example, without having included the header file
194 /// for a class \c XySimple, the following will still compile:
195 /// \code
196 /// #include "pxr/base/tf/refPtr.h"
197 ///
198 /// class XySimple;
199 ///
200 /// class Complicated {
201 /// public:
202 /// void SetSimple(const TfRefPtr<XySimple>& s) {
203 /// _simplePtr = s;
204 /// }
205 ///
206 /// TfRefPtr<XySimple> GetSimple() {
207 /// return _simplePtr;
208 /// }
209 ///
210 /// void Forget() {
211 /// _simplePtr.Reset();
212 /// }
213 ///
214 /// private:
215 /// TfRefPtr<XySimple> _simplePtr;
216 /// };
217 /// \endcode
218 ///
219 /// Note that the call \c Forget() (or \c SetSimple() for that matter)
220 /// may implicitly cause destruction of an \c XySimple object, if the count
221 /// of the object pointed to by \c _simplePtr drops to zero. Even though
222 /// the definition of \c XySimple is unknown, this compiles and works correctly.
223 ///
224 /// The only time that the definition of \c XySimple is required is when
225 /// putting a raw \c XySimple* into a \c TfRefPtr<XySimple>; note however, that
226 /// this should in fact only be done within the class definition of
227 /// \c XySimple itself.
228 ///
229 /// Other cases that require a definition of \c XySimple are parallel to
230 /// regular raw pointers, such as calling a member function, static or
231 /// dynamic casts (but not const casts) and using the \c TfTypeid
232 /// function. Transferring a \c TfWeakPtr to a \c TfRefPtr also
233 /// requires knowing the definition of \c XySimple.
234 ///
235 /// Sometimes a class may have many typedefs associated with it, having
236 /// to do with \c TfRefPtr or \c TfWeakPtr. If it is useful to use
237 /// the class opaquely, we recommend creating a separate file
238 /// as follows:
239 ///
240 /// \code
241 /// // file: proj/xy/simplePtrDefs.h
242 /// #include "pxr/base/tf/refPtr.h"
243 /// #include "pxr/base/tf/weakPtr.h"
244 ///
245 /// typedef TfRefPtr<class XySimple> XySimpleRefPtr;
246 /// typedef TfRefPtr<const class XySimple> XyConstSimpleRefPtr;
247 ///
248 /// // typedefs for TfWeakPtr<XySimple> would follow,
249 /// // if XySimple derives from TfWeakBase
250 /// \endcode
251 ///
252 /// The definition for \c XySimple would then use the typedefs:
253 ///
254 /// \code
255 /// #include "Proj/Xy/SimpleRefPtrDefs.h"
256 ///
257 /// class XySimple : public TfRefBase {
258 /// public:
259 /// static XySimpleRefPtr New();
260 /// ...
261 /// };
262 ///
263 /// \endcode
264 ///
265 /// The above pattern now allows a consumer of class \c XySimple the option
266 /// to include only \c simplePtrDefs.h, if using the type opaquely suffices,
267 /// or to include \c simple.h, if the class definition is required.
268 ///
269 ///
270 /// <B> Cyclic Dependencies </B>
271 ///
272 /// If you build a tree using \c TfRefPtr, and you only have pointers
273 /// from parent to child, everything is fine: if you "lose" the root of the
274 /// tree, the tree will correctly destroy itself.
275 ///
276 /// But what if children point back to parents? Then a simple parent/child
277 /// pair is stable, because the parent and child point at each other, and
278 /// even if nobody else has a pointer to the parent, the reference count
279 /// of the two nodes remains at one.
280 ///
281 /// The solution to this is to make one of the links (typically from child back
282 /// to parent) use a \c TfWeakPtr. If a class \c T is enabled for both
283 /// "guarding" (see \c TfWeakBase) and reference counting, then a \c TfRefPtr
284 /// can be converted to a \c TfWeakPtr (in this context, a "back pointer")
285 /// and vice versa.
286 ///
287 /// <B> Inheritance </B>
288 ///
289 ///
290 /// Reference-counted pointers obey the same rules with respect to inheritance
291 /// as regular pointers. In particular, if class \c Derived is derived
292 /// from class \c Base, then the following are legal:
293 ///
294 /// \code
295 /// TfRefPtr<Base> bPtr = new Base;
296 /// TfRefPtr<Derived> dPtr = new Derived;
297 ///
298 /// TfRefPtr<Base> b2Ptr = dPtr; // initialization
299 /// b2Ptr = dPtr; // assignment
300 /// b2Ptr == dPtr; // comparison
301 ///
302 /// dPtr = bPtr; // Not legal: compilation error
303 /// \endcode
304 ///
305 /// As the last example shows, initialization or assignment to
306 /// a \c TfRefPtr<Derived> from a \c TfRefPtr<Base> is illegal,
307 /// just as it is illegal to assign a \c Base* to a \c Derived*.
308 /// However, if \c Derived and \c Base are polymorphic
309 /// (i.e. have virtual functions) then the analogue of a \c dynamic_cast<>
310 /// is possible:
311 ///
312 /// \code
313 /// dPtr = TfDynamic_cast<TfRefPtr<Derived> >(bPtr);
314 /// \endcode
315 ///
316 /// Just like a regular \c dynamic_cast<> operation, the \c TfRefPtr
317 /// returned by \c TfDynamic_cast<> points to NULL if the conversion fails,
318 /// so that the operator can also be used to check types:
319 ///
320 /// \code
321 /// if (! TfDynamic_cast<TfRefPtr<T2> >(ptr))
322 /// // complain: ptr is not of type T2
323 /// \endcode
324 ///
325 /// Similarly, one can use the \c TfStatic_cast<> operator to statically
326 /// convert \c TfRefPtrs:
327 ///
328 /// \code
329 /// dPtr = TfStatic_cast<TfRefPtr<Derived> >(bPtr);
330 /// \endcode
331 ///
332 /// This is faster, but not as safe as using \c TfDynamic_cast.
333 ///
334 /// Finally, remember that in \c C++, a \c Derived** is
335 /// not a \c Base**, nor is a \c Derived*& a \c Base*&. This implies
336 /// that
337 ///
338 /// \code
339 /// TfRefPtr<Base>* bPtrPtr = &dPtr; // compilation error
340 /// TfRefPtr<Base>& bPtrRef = dPtr; // compilation error
341 /// const TfRefPtr<Base>&bPtrRef = dPtr; // OK
342 /// \endcode
343 ///
344 /// The last initialization is legal because the compiler implicitly
345 /// converts dPtr into a temporary variable of type \c TfRefPtr<Base>.
346 ///
347 ///
348 /// <B> Thread Safety </B>
349 ///
350 /// One more comment about thread-safety: the above examples are thread-safe
351 /// in the sense that if two or more threads create and destroy their \e own
352 /// \c TfRefPtr objects, the reference counts of the underlying objects are
353 /// always correct; said another way, the reference count it a thread-safe
354 /// quantity.
355 ///
356 /// However, it is never safe for two threads to simultaneously try to alter
357 /// the same \c TfRefPtr object, nor can two threads safely call methods on the
358 /// same underlying object unless that object itself guarantees thread safety.
359 ///
360 /// \anchor refPtr_Tracking
361 /// <B> Tracking References </B>
362 ///
363 /// The \c TfRefPtrTracker singleton can track \c TfRefPtr objects that
364 /// point to particular instances. The macros \c TF_DECLARE_REFBASE_TRACK
365 /// and \c TF_DEFINE_REFBASE_TRACK are used to enable tracking. Tracking
366 /// is enabled at compile time but which instances to track is chosen at
367 /// runtime.
368 ///
369 /// <B> Total Encapsulation </B>
370 /// \anchor refPtr_encapsulation
371 ///
372 /// If you're using \c TfRefPtrs on a type \c T, you probably want
373 /// to completely forbid clients from creating their own objects of
374 /// type \c T, and force them to go through \c TfRefPtrs. Such
375 /// encapsulation is strongly encouraged. Here is the recommended
376 /// technique:
377 ///
378 /// \code
379 ///
380 /// typedef TfRefPtr<class Simple> SimpleRefPtr;
381 ///
382 /// class Simple : public TfRefBase {
383 /// private: // use protected if you plan to derive later
384 /// Simple();
385 /// Simple(<arg-list>);
386 /// public:
387 /// static SimpleRefPtr New() {
388 /// return TfCreateRefPtr(new Simple);
389 /// }
390 ///
391 /// static SimpleRefPtr New(<arg-list>) {
392 /// return TfCreateRefPtr(new Simple(<arg-list>));
393 /// }
394 ///
395 /// ~Simple();
396 /// };
397 /// \endcode
398 ///
399 /// Clients can now only create objects of type \c Simple using a
400 /// \c TfRefPtr:
401 ///
402 /// \code
403 /// Simple s; // compilation error
404 /// SimpleRefPtr sPtr1 = new Simple; // compilation error
405 /// SimpleRefPtr sPtr2 = Simple::New(); // OK
406 /// SimpleRefPtr sPtr3 = Simple::New(<arg-list>); // Ok
407 /// \endcode
408 ///
409 
410 #include "pxr/pxr.h"
411 
413 #include "pxr/base/tf/hash.h"
414 #include "pxr/base/tf/nullPtr.h"
415 #include "pxr/base/tf/refBase.h"
418 #include "pxr/base/tf/api.h"
419 
420 #include "pxr/base/arch/hints.h"
421 
422 
423 #include <typeinfo>
424 #include <type_traits>
425 #include <cstddef>
426 
428 
429 // Tf_SupportsUniqueChanged is a metafunction that may be specialized to return
430 // false for classes (and all derived classes) that *cannot* ever invoke unique
431 // changed listeners.
432 template <class T>
434  static const bool Value = true;
435 };
436 
437 // Remnants are never able to support weak changed listeners.
438 class Tf_Remnant;
439 template <>
441  static const bool Value = false;
442 };
443 
444 class TfWeakBase;
445 
446 template <class T> class TfWeakPtr;
447 template <template <class> class X, class Y>
449 
450 // Functions used for tracking. Do not implement these.
451 inline void
452 Tf_RefPtrTracker_FirstRef(const void*, const TfRefBase *, const void*) { }
453 inline void
454 Tf_RefPtrTracker_LastRef(const void*, const TfRefBase *, const void*) { }
455 inline void
456 Tf_RefPtrTracker_New(const void*, const TfRefBase *, const void*) { }
457 inline void
458 Tf_RefPtrTracker_Delete(const void*, const TfRefBase *, const void*) { }
459 inline void
460 Tf_RefPtrTracker_Assign(const void*, const TfRefBase *,
461  const TfRefBase *, const void*) { }
462 
463 // This code is used to increment and decrement ref counts in the common case.
464 // It may lock and invoke the unique changed listener, if the reference count
465 // becomes unique or non-unique.
467  static inline void
468  AddRef(TfRefBase const *refBase) {
469  if (ARCH_UNLIKELY(!refBase)) {
470  return;
471  }
472  const auto relaxed = std::memory_order_relaxed;
473  // Read the current count value.
474  std::atomic_int &counter = refBase->_GetRefCount();
475  int prevCount = counter.load(relaxed);
476  if (ARCH_UNLIKELY(prevCount < 0)) {
477  // We need to invoke the unique changed listener if count goes from
478  // -1 -> -2. Try to CAS the value to one more count if it looks
479  // like we won't take it from -1 -> -2. If that works, we're done.
480  // If not, we'll call an out-of-line function that handles the
481  // locking part.
482  if (prevCount != -1 && counter.
483  compare_exchange_weak(prevCount, prevCount-1, relaxed)) {
484  return;
485  }
486  _AddRefMaybeLocked(refBase, prevCount);
487  }
488  else {
489  // Just bump the count.
490  counter.fetch_add(1, relaxed);
491  }
492  }
493 
494  static inline bool
495  RemoveRef(TfRefBase const* refBase) {
496  if (ARCH_UNLIKELY(!refBase)) {
497  return false;
498  }
499  const auto relaxed = std::memory_order_relaxed;
500  const auto release = std::memory_order_release;
501  // Read the current count value.
502  std::atomic_int &counter = refBase->_GetRefCount();
503  int prevCount = counter.load(relaxed);
504  if (ARCH_UNLIKELY(prevCount < 0)) {
505  // We need to invoke the unique changed listener if count goes from
506  // -2 -> -1. Try to CAS the value to one less count if it looks
507  // like we won't take it from -2 -> -1. If that works, we're done.
508  // If not, we'll call an out-of-line function that handles the
509  // locking part.
510  if (prevCount != -2 && counter.
511  compare_exchange_weak(prevCount, prevCount+1, release)) {
512  return prevCount == -1;
513  }
514  return _RemoveRefMaybeLocked(refBase, prevCount);
515  }
516  else {
517  // Just drop the count.
518  return counter.fetch_sub(1, release) == 1;
519  }
520  }
521 
522  // Increment ptr's count if it is not zero. Return true if done so
523  // successfully, false if its count is zero.
524  TF_API static bool
525  AddRefIfNonzero(TfRefBase const *refBase);
526 
527  TF_API static void
528  _AddRefMaybeLocked(TfRefBase const *refBase, int prevCount);
529 
530  TF_API static bool
531  _RemoveRefMaybeLocked(TfRefBase const *refBase, int prevCount);
532 
533 };
534 
535 // This code is used to increment and decrement ref counts in the case where
536 // the object pointed to explicitly does not support unique changed listeners.
538  static inline void
539  AddRef(TfRefBase const *refBase) {
540  if (ARCH_UNLIKELY(!refBase)) {
541  return;
542  }
543  refBase->_GetRefCount().fetch_add(1, std::memory_order_relaxed);
544  }
545 
546  static inline bool
547  RemoveRef(TfRefBase const *refBase) {
548  if (ARCH_UNLIKELY(!refBase)) {
549  return false;
550  }
551  return refBase->_GetRefCount()
552  .fetch_sub(1, std::memory_order_release) == 1;
553  }
554 
555  // Increment ptr's count if it is not zero. Return true if done so
556  // successfully, false if its count is zero.
557  static inline bool
558  AddRefIfNonzero(TfRefBase const *refBase) {
559  if (ARCH_UNLIKELY(!refBase)) {
560  return false;
561  }
562  auto &counter = refBase->_GetRefCount();
563  int prevCount = counter.load(std::memory_order_relaxed);
564  while (prevCount) {
565  if (counter.compare_exchange_weak(prevCount, prevCount+1)) {
566  return true;
567  }
568  }
569  return false;
570  }
571 };
572 
573 // Helper to post a fatal error when a NULL Tf pointer is dereferenced.
574 [[noreturn]]
575 TF_API void
577 
578 /// \class TfRefPtr
579 /// \ingroup group_tf_Memory
580 ///
581 /// Reference-counted smart pointer utility class
582 ///
583 /// The \c TfRefPtr class implements a reference counting on objects
584 /// that inherit from \c TfRefBase.
585 ///
586 /// For more information, see either the \ref refPtr_QuickStart "Quick Start"
587 /// example or read the \ref refPtr_DetailedDiscussion "detailed discussion".
588 ///
589 template <class T>
590 class TfRefPtr {
591  // Select the counter based on whether T supports unique changed listeners.
592  using _Counter = typename std::conditional<
597 
598  static constexpr T *_NullT = nullptr;
599 
600 public:
601  /// Convenience type accessor to underlying type \c T for template code.
602  typedef T DataType;
603 
604 
605  template <class U> struct Rebind {
606  typedef TfRefPtr<U> Type;
607  };
608 
609  /// Initialize pointer to nullptr.
610  ///
611  /// The default constructor leaves the pointer initialized to point to the
612  /// NULL object. Attempts to use the \c -> operator will cause an abort
613  /// until the pointer is given a value.
614  TfRefPtr() : _refBase(nullptr) {
615  Tf_RefPtrTracker_New(this, _refBase, _NullT);
616  }
617 
618  /// Moves the pointer managed by \p p to \c *this.
619  ///
620  /// After construction, \c *this will point to the object \p p had
621  /// been pointing at and \p p will be pointing at the NULL object.
622  /// The reference count of the object being pointed at does not
623  /// change.
624  TfRefPtr(TfRefPtr<T>&& p) : _refBase(p._refBase) {
625  p._refBase = nullptr;
626  Tf_RefPtrTracker_New(this, _refBase, _NullT);
627  Tf_RefPtrTracker_Assign(&p, p._refBase, _refBase, _NullT);
628  }
629 
630  /// Initializes \c *this to point at \p p's object.
631  ///
632  /// Increments \p p's object's reference count.
633  TfRefPtr(const TfRefPtr<T>& p) : _refBase(p._refBase) {
634  _AddRef();
635  Tf_RefPtrTracker_New(this, _refBase, _NullT);
636  }
637 
638  /// Initializes \c *this to point at \p gp's object.
639  ///
640  /// Increments \p gp's object's reference count.
641  template <template <class> class X, class U>
642  inline TfRefPtr(const TfWeakPtrFacade<X, U>& p,
643  typename std::enable_if<
645  >::type * = 0);
646 
647  /// Transfer a raw pointer to a reference-counted pointer.
648  ///
649  /// The \c TfCreateRefPtr() function should only be used from within a
650  /// static \c New() function (or similarly, a \c Clone() function) of a
651  /// reference-counted class. Reference-counted objects have their
652  /// reference count initially set to one to account for the fact that a
653  /// newly created object must always persist at least until its \c New()
654  /// function returns. Therefore, the transfer of the pointer returned by
655  /// \c new into a reference pointer must \e not increase the reference
656  /// count. The transfer of the raw pointer returned by \c new into the
657  /// object returned by \c New() is a "transfer of ownership" and does not
658  /// represent an additional reference to the object.
659  ///
660  /// In summary, this code is wrong, and will return an object that can
661  /// never be destroyed:
662  ///
663  /// \code
664  /// SimpleRefPtr Simple::New() {
665  /// return SimpleRefPtr(new Simple); // legal, but leaks memory: beware!!
666  /// }
667  /// \endcode
668  ///
669  /// The correct form is
670  ///
671  /// \code
672  /// SimpleRefPtr Simple::New() {
673  /// return TfCreateRefPtr(new Simple);
674  /// }
675  /// \endcode
676  ///
677  /// Note also that a function which is essentially like \c New(),
678  /// for example \c Clone(), would also want to use \c TfCreateRefPtr().
679 #if defined(doxygen)
680  friend inline TfRefPtr TfCreateRefPtr(T*);
681 #else
682  template <class U>
683  friend inline TfRefPtr<U> TfCreateRefPtr(U*);
684 #endif
685 
686  /// Initializes to point at \c *ptr.
687  ///
688  /// Increments \c *ptr's reference count. Note that newly constructed
689  /// objects start with a reference count of one. Therefore, you should \e
690  /// NOT use this constructor (either implicitly or explicitly) from within
691  /// a \c New() function. Use \c TfCreateRefPtr() instead.
692  template <class U>
693  explicit TfRefPtr(
694  U* ptr, typename std::enable_if<
696  _refBase(ptr)
697  {
698  _AddRef();
699  Tf_RefPtrTracker_New(this, _refBase, _NullT);
700  }
701 
702  /// Implicit conversion from \a TfNullPtr to TfRefPtr.
703  TfRefPtr(TfNullPtrType) : _refBase(nullptr)
704  {
705  Tf_RefPtrTracker_New(this, _refBase, _NullT);
706  }
707 
708  /// Implicit conversion from \a nullptr to TfRefPtr.
709  TfRefPtr(std::nullptr_t) : _refBase(nullptr)
710  {
711  Tf_RefPtrTracker_New(this, _refBase, _NullT);
712  }
713 
714  /// Assigns pointer to point at \c p's object, and increments reference
715  /// count.
716  ///
717  /// The object (if any) pointed at before the assignment has its
718  /// reference count decremented, while the object newly pointed at
719  /// has its reference count incremented.
720  /// If the object previously pointed to now has nobody left to point at it,
721  /// the object will typically be destroyed at this point.
722  ///
723  /// An assignment
724  /// \code
725  /// ptr = TfNullPtr;
726  /// \endcode
727  ///
728  /// can be used to make \c ptr "forget" where it is pointing; note
729  /// however that this has an important side effect, since it
730  /// decrements the reference count of the object previously pointed
731  /// to by \c ptr, possibly triggering destruction of that object.
733  //
734  // It is quite possible for
735  // ptr = TfNullPtr;
736  // to delete the space that ptr actually lives in (this happens
737  // when you use a circular reference to keep an object alive).
738  // To avoid a crash, we have to ensure that deletion of the object
739  // is the last thing done in the assignment; so we use some
740  // local variables to help us out.
741  //
742 
743  Tf_RefPtrTracker_Assign(this, p._refBase, _refBase, _NullT);
744 
745  const TfRefBase* tmp = _refBase;
746  _refBase = p._refBase;
747 
748  p._AddRef(); // first!
749  _RemoveRef(tmp); // second!
750  return *this;
751  }
752 
753  /// Moves the pointer managed by \p p to \c *this and leaves \p p
754  /// pointing at the NULL object.
755  ///
756  /// The object (if any) pointed at before the assignment has its
757  /// reference count decremented, while the reference count of the
758  /// object newly pointed at is not changed.
760  // See comment in assignment operator.
761  Tf_RefPtrTracker_Assign(this, p._refBase, _refBase, _NullT);
762  Tf_RefPtrTracker_Assign(&p, nullptr, p._refBase, _NullT);
763 
764  const TfRefBase* tmp = _refBase;
765  _refBase = p._refBase;
766  p._refBase = nullptr;
767 
768  _RemoveRef(tmp);
769  return *this;
770  }
771 
772  /// Decrements reference count of object being pointed to.
773  ///
774  /// If the reference count of the object (if any) that was just pointed at
775  /// reaches zero, the object will typically be destroyed at this point.
777  Tf_RefPtrTracker_Delete(this, _refBase, _NullT);
778  _RemoveRef(_refBase);
779  }
780 
781  /// Initializes to point at \c p's object, and increments reference count.
782  ///
783  /// This initialization is legal only if
784  /// \code
785  /// U* uPtr;
786  /// T* tPtr = uPtr;
787  /// \endcode
788  /// is legal.
789 #if !defined(doxygen)
790  template <class U>
791 #endif
792  TfRefPtr(const TfRefPtr<U>& p) : _refBase(p._refBase) {
793  static_assert(std::is_convertible<U*, T*>::value, "");
794  _AddRef();
795  Tf_RefPtrTracker_New(this, _refBase, _NullT);
796  }
797 
798  /// Moves the pointer managed by \p p to \c *this and leaves \p p
799  /// pointing at the NULL object. The reference count of the object
800  /// being pointed to is not changed.
801  ///
802  /// This initialization is legal only if
803  /// \code
804  /// U* uPtr;
805  /// T* tPtr = uPtr;
806  /// \endcode
807  /// is legal.
808 #if !defined(doxygen)
809  template <class U>
810 #endif
811  TfRefPtr(TfRefPtr<U>&& p) : _refBase(p._refBase) {
812  static_assert(std::is_convertible<U*, T*>::value, "");
813  p._refBase = nullptr;
814  Tf_RefPtrTracker_New(this, _refBase, _NullT);
815  Tf_RefPtrTracker_Assign(&p, p._refBase, _refBase, _NullT);
816  }
817 
818  /// Assigns pointer to point at \c p's object, and increments reference
819  /// count.
820  ///
821  /// This assignment is legal only if
822  /// \code
823  /// U* uPtr;
824  /// T* tPtr;
825  /// tPtr = uPtr;
826  /// \endcode
827  /// is legal.
828 #if !defined(doxygen)
829  template <class U>
830 #endif
832  static_assert(std::is_convertible<U*, T*>::value, "");
833 
834  Tf_RefPtrTracker_Assign(this, p._refBase, _refBase, _NullT);
835  const TfRefBase* tmp = _refBase;
836  _refBase = p._GetData();
837  p._AddRef(); // first!
838  _RemoveRef(tmp); // second!
839  return *this;
840  }
841 
842  /// Moves the pointer managed by \p p to \c *this and leaves \p p
843  /// pointing at the NULL object. The reference count of the object
844  /// being pointed to is not changed.
845  ///
846  /// This assignment is legal only if
847  /// \code
848  /// U* uPtr;
849  /// T* tPtr;
850  /// tPtr = uPtr;
851  /// \endcode
852  /// is legal.
853 #if !defined(doxygen)
854  template <class U>
855 #endif
857  static_assert(std::is_convertible<U*, T*>::value, "");
858 
859  Tf_RefPtrTracker_Assign(this, p._refBase, _refBase, _NullT);
860  Tf_RefPtrTracker_Assign(&p, nullptr, p._refBase, _NullT);
861  const TfRefBase* tmp = _refBase;
862  _refBase = p._GetData();
863  p._refBase = nullptr;
864  _RemoveRef(tmp);
865  return *this;
866  }
867 
868  /// Returns true if \c *this and \c p point to the same object (or if they
869  /// both point to NULL).
870  ///
871  /// The comparison is legal only if a \c T* and a \c U* are comparable.
872 #if !defined(doxygen)
873  template <class U>
874 #endif
875  auto operator==(const TfRefPtr<U>& p) const
876  -> decltype(std::declval<T *>() == std::declval<U *>(), bool()) {
877  return _refBase == p._refBase;
878  }
879 
880  /// Returns true if \c *this and \c p do not point to the same object.
881  ///
882  /// The comparison is legal only if a \c T* and a \c U* are comparable.
883 #if !defined(doxygen)
884  template <class U>
885 #endif
886  auto operator!=(const TfRefPtr<U>& p) const
887  -> decltype(std::declval<T *>() != std::declval<U *>(), bool()) {
888  return _refBase != p._refBase;
889  }
890 
891  /// Returns true if the address of the object pointed to by \c *this
892  /// compares less than the address of the object pointed to by \p p.
893  ///
894  /// The comparison is legal only if a \c T* and a \c U* are comparable.
895 #if !defined(doxygen)
896  template <class U>
897 #endif
898  auto operator<(const TfRefPtr<U>& p) const
899  -> decltype(std::declval<T *>() < std::declval<U *>(), bool()) {
900  return _refBase < p._refBase;
901  }
902 
903 #if !defined(doxygen)
904  template <class U>
905 #endif
906  auto operator>(const TfRefPtr<U>& p) const
907  -> decltype(std::declval<T *>() > std::declval<U *>(), bool()) {
908  return _refBase > p._refBase;
909  }
910 
911 #if !defined(doxygen)
912  template <class U>
913 #endif
914  auto operator<=(const TfRefPtr<U>& p) const
915  -> decltype(std::declval<T *>() <= std::declval<U *>(), bool()) {
916  return _refBase <= p._refBase;
917  }
918 
919 #if !defined(doxygen)
920  template <class U>
921 #endif
922  auto operator>=(const TfRefPtr<U>& p) const
923  -> decltype(std::declval<T *>() >= std::declval<U *>(), bool()) {
924  return _refBase >= p._refBase;
925  }
926 
927  /// Accessor to \c T's public members.
928  T* operator->() const {
929  if (_refBase) {
930  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
931  }
933  TF_CALL_CONTEXT, typeid(TfRefPtr).name());
934  }
935 
936  /// Dereferences the stored pointer.
937  T& operator *() const {
938  return *operator->();
939  }
940 
941 #if !defined(doxygen)
942  using UnspecifiedBoolType = const TfRefBase * (TfRefPtr::*);
943 #endif
944 
945  /// True if the pointer points to an object.
946  operator UnspecifiedBoolType() const {
947  return _refBase ? &TfRefPtr::_refBase : nullptr;
948  }
949 
950  /// True if the pointer points to \c NULL.
951  bool operator !() const {
952  return _refBase == nullptr;
953  }
954 
955  /// Swap this pointer with \a other.
956  /// After this operation, this pointer will point to what \a other
957  /// formerly pointed to, and \a other will point to what this pointer
958  /// formerly pointed to.
959  void swap(TfRefPtr &other) {
960  Tf_RefPtrTracker_Assign(this, other._refBase, _refBase, _NullT);
961  Tf_RefPtrTracker_Assign(&other, _refBase, other._refBase, _NullT);
962  std::swap(_refBase, other._refBase);
963  }
964 
965  /// Set this pointer to point to no object.
966  /// Equivalent to assignment with TfNullPtr.
967  void Reset() {
968  *this = TfNullPtr;
969  }
970 
971 private:
972  const TfRefBase* _refBase;
973 
974  template <class HashState, class U>
975  friend inline void TfHashAppend(HashState &, const TfRefPtr<U>&);
976  template <class U>
977  friend inline size_t hash_value(const TfRefPtr<U>&);
978 
979  friend T *get_pointer(TfRefPtr const &p) {
980  return static_cast<T *>(const_cast<TfRefBase *>(p._refBase));
981  }
982 
983  // Used to distinguish construction in TfCreateRefPtr.
984  class _CreateRefPtr { };
985 
986  // private constructor, used by TfCreateRefPtr()
987  TfRefPtr(T* ptr, _CreateRefPtr /* unused */)
988  : _refBase(ptr)
989  {
990  /* reference count is NOT bumped */
991  Tf_RefPtrTracker_FirstRef(this, _refBase, _NullT);
992  Tf_RefPtrTracker_New(this, _refBase, _NullT);
993  }
994 
995  // Hide confusing internals of actual C++ definition (e.g. DataType)
996  // for doxygen output:
997 
998  /// Allows dynamic casting of a \c TfRefPtr.
999  ///
1000  /// If it is legal to dynamically cast a \c T* to a \c D* , then
1001  /// the following is also legal:
1002  /// \code
1003  /// TfRefPtr<T> tPtr = ... ;
1004  /// TfRefPtr<D> dPtr;
1005  ///
1006  /// if (!(dPtr = TfDynamic_cast< TfRefPtr<D> >(tPtr)))
1007  /// ...; // cast failed
1008  /// \endcode
1009  /// The runtime performance of this function is exactly the same
1010  /// as a \c dynamic_cast (i.e. one virtual function call). If the pointer
1011  /// being cast is NULL or does not point to an object of the requisite
1012  /// type, the result is a \c TfRefPtr pointing to NULL.
1013 #if defined(doxygen)
1014  // Sanitized for documentation:
1015  template <class D>
1016  friend inline TfRefPtr<D> TfDynamic_cast(const TfRefPtr<T>&);
1017 #else
1018  template <class D, class B>
1020  TfDynamic_cast(const TfRefPtr<B>&);
1021 
1022  template <class D, class B>
1025 #endif
1026 
1027  /// Allows static casting of a \c TfRefPtr.
1028  ///
1029  /// If it is legal to statically cast a \c T* to a \c D* , then
1030  /// the following is also legal:
1031  /// \code
1032  /// TfRefPtr<T> tPtr = ... ;
1033  /// TfRefPtr<D> dPtr;
1034  ///
1035  /// dPtr = TfStatic_cast< TfRefPtr<D> >(tPtr);
1036  /// \endcode
1037  /// The runtime performance of this function is exactly the same
1038  /// as a regular \c TfRefPtr initialization, since the cost of
1039  /// the underlying \c static_cast is zero. Of course, a \c TfDynamic_cast
1040  /// is preferred, assuming the underlying types are polymorphic
1041  /// (i.e. have virtual functions).
1042  ///
1043 #if defined(doxygen)
1044  // Sanitized for documentation:
1045  template <class D>
1046  friend inline TfRefPtr<D> TfStatic_cast(const TfRefPtr<T>&);
1047 #else
1048  template <class D, class B>
1050  TfStatic_cast(const TfRefPtr<B>&);
1051 
1052 #endif
1053 
1054  /// Allows const casting of a \c TfRefPtr.
1055  ///
1056  /// The following is always legal:
1057  /// \code
1058  /// TfRefPtr<const T> cPtr = ...;
1059  /// TfRefPtr<T> tPtr;
1060  ///
1061  /// tPtr = TfConst_cast< TfRefPtr<T> >(cPtr);
1062  /// \endcode
1063  /// As with the C++ \c const_cast operator, use of this function is
1064  /// discouraged.
1065 #if defined(doxygen)
1066  // Sanitized for documentation:
1067  template <class D>
1068  friend inline TfRefPtr<D> TfConst_cast(const TfRefPtr<const D>&);
1069 #else
1070  template <class D>
1073 #endif
1074 
1075  T* _GetData() const {
1076  return static_cast<T*>(const_cast<TfRefBase*>(_refBase));
1077  }
1078 
1079  /// Call \c typeid on the object pointed to by a \c TfRefPtr.
1080  ///
1081  /// If \c ptr is a \c TfRefPtr, \c typeid(ptr) will return
1082  /// type information about the \c TfRefPtr. To access type
1083  /// information about the object pointed to by a \c TfRefPtr,
1084  /// one can use \c TfTypeid.
1085 
1086  template <class U>
1087  friend const std::type_info& TfTypeid(const TfRefPtr<U>& ptr);
1088 
1089  void _AddRef() const {
1090  _Counter::AddRef(_refBase);
1091  }
1092 
1093  void _RemoveRef(const TfRefBase* ptr) const {
1094  if (_Counter::RemoveRef(ptr)) {
1095  Tf_RefPtrTracker_LastRef(this, ptr, _NullT);
1096  delete ptr;
1097  }
1098  }
1099 
1100 #if ! defined(doxygen)
1101  // doxygen is very confused by this. It declares all TfRefPtrs
1102  // to be friends.
1103  template <class U> friend class TfRefPtr;
1104  template <class U> friend class TfWeakPtr;
1105  friend class Tf_Remnant;
1106 
1107  template <class U>
1109 #endif
1110  friend class TfWeakBase;
1111 };
1112 
1113 #if !defined(doxygen)
1114 
1115 //
1116 // nullptr comparisons
1117 //
1118 // These are provided to avoid ambiguous overloads due to
1119 // TfWeakPtrFacade::Derived comparisons with TfRefPtr.
1120 //
1121 
1122 template <class T>
1123 inline bool operator== (const TfRefPtr<T> &p, std::nullptr_t)
1124 {
1125  return !p;
1126 }
1127 template <class T>
1128 inline bool operator== (std::nullptr_t, const TfRefPtr<T> &p)
1129 {
1130  return !p;
1131 }
1132 
1133 template <class T>
1134 inline bool operator!= (const TfRefPtr<T> &p, std::nullptr_t)
1135 {
1136  return !(p == nullptr);
1137 }
1138 template <class T>
1139 inline bool operator!= (std::nullptr_t, const TfRefPtr<T> &p)
1140 {
1141  return !(nullptr == p);
1142 }
1143 
1144 template <class T>
1145 inline bool operator< (const TfRefPtr<T> &p, std::nullptr_t)
1146 {
1147  return std::less<const TfRefBase *>()(get_pointer(p), nullptr);
1148 }
1149 template <class T>
1150 inline bool operator< (std::nullptr_t, const TfRefPtr<T> &p)
1151 {
1152  return std::less<const TfRefBase *>()(nullptr, get_pointer(p));
1153 }
1154 
1155 template <class T>
1156 inline bool operator<= (const TfRefPtr<T> &p, std::nullptr_t)
1157 {
1158  return !(nullptr < p);
1159 }
1160 template <class T>
1161 inline bool operator<= (std::nullptr_t, const TfRefPtr<T> &p)
1162 {
1163  return !(p < nullptr);
1164 }
1165 
1166 template <class T>
1167 inline bool operator> (const TfRefPtr<T> &p, std::nullptr_t)
1168 {
1169  return nullptr < p;
1170 }
1171 template <class T>
1172 inline bool operator> (std::nullptr_t, const TfRefPtr<T> &p)
1173 {
1174  return p < nullptr;
1175 }
1176 
1177 template <class T>
1178 inline bool operator>= (const TfRefPtr<T> &p, std::nullptr_t)
1179 {
1180  return !(p < nullptr);
1181 }
1182 template <class T>
1183 inline bool operator>= (std::nullptr_t, const TfRefPtr<T> &p)
1184 {
1185  return !(nullptr < p);
1186 }
1187 
1188 
1189 template <typename T>
1191  return TfRefPtr<T>(ptr, typename TfRefPtr<T>::_CreateRefPtr());
1192 }
1193 
1194 template <class T>
1195 const std::type_info&
1197 {
1198  if (ARCH_UNLIKELY(!ptr._refBase))
1199  TF_FATAL_ERROR("called TfTypeid on NULL TfRefPtr");
1200 
1201  return typeid(*ptr._GetData());
1202 }
1203 
1204 template <class D, class T>
1205 inline
1208 {
1209  typedef TfRefPtr<typename D::DataType> RefPtr;
1210  return RefPtr(dynamic_cast<typename D::DataType*>(ptr._GetData()));
1211 }
1212 
1213 template <class D, class T>
1214 inline
1217 {
1218  typedef TfRefPtr<typename D::DataType> RefPtr;
1219  return RefPtr(TfSafeDynamic_cast<typename D::DataType*>(ptr._GetData()));
1220 }
1221 
1222 template <class D, class T>
1223 inline
1226 {
1227  typedef TfRefPtr<typename D::DataType> RefPtr;
1228  return RefPtr(static_cast<typename D::DataType*>(ptr._GetData()));
1229 }
1230 
1231 template <class T>
1232 inline
1235 {
1236  // this ugly cast allows TfConst_cast to work without requiring
1237  // a definition for T.
1238  typedef TfRefPtr<typename T::DataType> NonConstRefPtr;
1239  return *((NonConstRefPtr*)(&ptr));
1240 }
1241 
1242 // Specialization: prevent construction of a TfRefPtr<TfRefBase>.
1243 
1244 template <>
1246 private:
1247  TfRefPtr() = delete;
1248 };
1249 
1250 template <>
1251 class TfRefPtr<const TfRefBase> {
1252 private:
1253  TfRefPtr() = delete;
1254 };
1255 
1256 template <class T>
1258  static T* GetRawPtr(const TfRefPtr<T>& t) {
1259  return t.operator-> ();
1260  }
1261 
1263  return TfRefPtr<T>(ptr);
1264  }
1265 
1266  static bool IsNull(const TfRefPtr<T>& t) {
1267  return !t;
1268  }
1269 
1272 };
1273 
1274 template <class T>
1275 struct TfTypeFunctions<TfRefPtr<const T> > {
1276  static const T* GetRawPtr(const TfRefPtr<const T>& t) {
1277  return t.operator-> ();
1278  }
1279 
1281  return TfRefPtr<const T>(ptr);
1282  }
1283 
1284  static bool IsNull(const TfRefPtr<const T>& t) {
1285  return !t;
1286  }
1287 
1289 };
1290 
1291 #endif
1292 
1293 #if !defined(doxygen)
1294 
1295 template <class T>
1296 inline void
1298 {
1299  lhs.swap(rhs);
1300 }
1301 
1302 template <class T>
1303 inline size_t
1305 {
1306  return TfHash()(ptr);
1307 }
1308 
1309 template <class HashState, class T>
1310 inline void
1311 TfHashAppend(HashState &h, const TfRefPtr<T> &ptr)
1312 {
1313  h.Append(get_pointer(ptr));
1314 }
1315 
1316 #endif // !doxygen
1317 
1318 #define TF_SUPPORTS_REFPTR(T) std::is_base_of_v<TfRefBase, T>
1319 
1321 
1322 #endif // PXR_BASE_TF_REF_PTR_H
void swap(ArAssetInfo &lhs, ArAssetInfo &rhs)
Definition: assetInfo.h:57
type
Definition: core.h:556
static void Class_Object_MUST_Be_Passed_By_Address()
Definition: refPtr.h:1270
auto operator==(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >()==std::declval< U * >(), bool())
Definition: refPtr.h:875
static TF_API bool _RemoveRefMaybeLocked(TfRefBase const *refBase, int prevCount)
TfRefPtr< T > TfCreateRefPtr(T *ptr)
Definition: refPtr.h:1190
#define TF_CALL_CONTEXT
Definition: callContext.h:30
TfRefPtr< typename T::DataType > TfConst_cast(const TfRefPtr< const typename T::DataType > &ptr)
Definition: refPtr.h:1234
static TfRefPtr< const T > ConstructFromRawPtr(T *ptr)
Definition: refPtr.h:1280
#define TF_API
Definition: api.h:23
friend size_t hash_value(const TfRefPtr< U > &)
TfRefPtr(TfNullPtrType)
Implicit conversion from TfNullPtr to TfRefPtr.
Definition: refPtr.h:703
Y
Definition: ImathEuler.h:184
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
Definition: UT_ArraySet.h:1699
auto operator>=(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >() >=std::declval< U * >(), bool())
Definition: refPtr.h:922
GLsizei const GLfloat * value
Definition: glcorearb.h:824
const TfRefBase *(TfRefPtr::*) UnspecifiedBoolType
Definition: refPtr.h:942
static bool IsNull(const TfRefPtr< T > &t)
Definition: refPtr.h:1266
TF_API const TfNullPtrType TfNullPtr
auto operator>(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >() > std::declval< U * >(), bool())
Definition: refPtr.h:906
X
Definition: ImathEuler.h:183
static void Class_Object_MUST_Be_Passed_By_Address()
Definition: refPtr.h:1288
friend T * get_pointer(TfRefPtr const &p)
Definition: refPtr.h:979
friend TfRefPtr< U > TfCreateRefPtr(U *)
static void AddRef(TfRefBase const *refBase)
Definition: refPtr.h:539
TfRefPtr< T > & operator=(const TfRefPtr< T > &p)
Definition: refPtr.h:732
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:63
bool operator!() const
True if the pointer points to NULL.
Definition: refPtr.h:951
friend TfRefPtr< typename D::DataType > TfSafeDynamic_cast(const TfRefPtr< B > &)
Definition: hash.h:472
TfRefPtr(U *ptr, typename std::enable_if< std::is_convertible< U *, T * >::value >::type *=nullptr)
Definition: refPtr.h:693
T & operator*() const
Dereferences the stored pointer.
Definition: refPtr.h:937
static bool RemoveRef(TfRefBase const *refBase)
Definition: refPtr.h:495
atomic< int > atomic_int
Definition: atomic.h:25
TfRefPtr< typename D::DataType > TfDynamic_cast(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1207
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
TF_API void Tf_PostNullSmartPtrDereferenceFatalError(const TfCallContext &, const char *)
static void AddRef(TfRefBase const *refBase)
Definition: refPtr.h:468
TfRefPtr(const TfRefPtr< T > &p)
Definition: refPtr.h:633
void Tf_RefPtrTracker_Delete(const void *, const TfRefBase *, const void *)
Definition: refPtr.h:458
static const T * GetRawPtr(const TfRefPtr< const T > &t)
Definition: refPtr.h:1276
TfRefPtr(TfRefPtr< U > &&p)
Definition: refPtr.h:811
A generic, discriminated value, whose type may be queried dynamically.
Definition: Value.h:45
static bool RemoveRef(TfRefBase const *refBase)
Definition: refPtr.h:547
auto operator!=(const TfRefPtr< U > &p) const -> decltype(std::declval< T * >()!=std::declval< U * >(), bool())
Definition: refPtr.h:886
TfRefPtr< T > & operator=(TfRefPtr< U > &&p)
Definition: refPtr.h:856
static TF_API void _AddRefMaybeLocked(TfRefBase const *refBase, int prevCount)
#define TF_FATAL_ERROR
static T * GetRawPtr(const TfRefPtr< T > &t)
Definition: refPtr.h:1258
bool operator!=(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Inequality operator, does exact floating point comparisons.
Definition: Mat3.h:556
const std::type_info & TfTypeid(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1196
friend const std::type_info & TfTypeid(const TfRefPtr< U > &ptr)
void Tf_RefPtrTracker_LastRef(const void *, const TfRefBase *, const void *)
Definition: refPtr.h:454
static bool AddRefIfNonzero(TfRefBase const *refBase)
Definition: refPtr.h:558
TfRefPtr< typename D::DataType > TfSafeDynamic_cast(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1216
GLuint const GLchar * name
Definition: glcorearb.h:786
TfRefPtr< typename D::DataType > TfStatic_cast(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1225
TfRefPtr(TfRefPtr< T > &&p)
Definition: refPtr.h:624
GLdouble t
Definition: glad.h:2397
friend TfRefPtr< typename D::DataType > TfDynamic_cast(const TfRefPtr< B > &)
size_t hash_value(const TfRefPtr< T > &ptr)
Definition: refPtr.h:1304
bool operator>(const TfRefPtr< T > &p, std::nullptr_t)
Definition: refPtr.h:1167
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
static TF_API bool AddRefIfNonzero(TfRefBase const *refBase)
TfRefPtr(std::nullptr_t)
Implicit conversion from nullptr to TfRefPtr.
Definition: refPtr.h:709
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
void Tf_RefPtrTracker_Assign(const void *, const TfRefBase *, const TfRefBase *, const void *)
Definition: refPtr.h:460
TfRefPtr< T > & operator=(TfRefPtr< T > &&p)
Definition: refPtr.h:759
static bool IsNull(const TfRefPtr< const T > &t)
Definition: refPtr.h:1284
TfRefPtr()
Definition: refPtr.h:614
void Tf_RefPtrTracker_New(const void *, const TfRefBase *, const void *)
Definition: refPtr.h:456
auto ptr(T p) -> const void *
Definition: format.h:4331
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void Tf_RefPtrTracker_FirstRef(const void *, const TfRefBase *, const void *)
Definition: refPtr.h:452
static TfRefPtr< T > ConstructFromRawPtr(T *ptr)
Definition: refPtr.h:1262
friend void TfHashAppend(HashState &, const TfRefPtr< U > &)
void TfHashAppend(HashState &h, const TfRefPtr< T > &ptr)
Definition: refPtr.h:1311
~TfRefPtr()
Definition: refPtr.h:776
T DataType
Convenience type accessor to underlying type T for template code.
Definition: refPtr.h:602
friend TfRefPtr< typename D::DataType > TfStatic_cast(const TfRefPtr< B > &)
bool operator>=(const TfRefPtr< T > &p, std::nullptr_t)
Definition: refPtr.h:1178
TfRefPtr(const TfRefPtr< U > &p)
Definition: refPtr.h:792
friend TfRefPtr< U > TfCreateRefPtrFromProtectedWeakPtr(TfWeakPtr< U > const &)
TfRefPtr< T > & operator=(const TfRefPtr< U > &p)
Definition: refPtr.h:831
static void Class_Object_MUST_Not_Be_Const()
Definition: refPtr.h:1271
T * operator->() const
Accessor to T's public members.
Definition: refPtr.h:928
friend TfRefPtr< typename D::DataType > TfConst_cast(const TfRefPtr< const typename D::DataType > &)
bool operator==(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Equality operator, does exact floating point comparisons.
Definition: Mat3.h:542
void Reset()
Definition: refPtr.h:967
void swap(TfRefPtr &other)
Definition: refPtr.h:959
TfRefPtr< U > Type
Definition: refPtr.h:606