// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_BASE_TF_REF_PTR_H #define PXR_BASE_TF_REF_PTR_H /// \file tf/refPtr.h /// \ingroup group_tf_Memory /// Reference counting. /// /// \anchor refPtr_QuickStart /// Quick Start /// /// Here is how to make a class \c Bunny usable through \c TfRefPtr. /// /// \code /// #include "pxr/base/tf/refPtr.h" /// typedef TfRefPtr BunnyRefPtr; /// /// class Bunny : public TfRefBase { /// public: /// static BunnyRefPtr New() { /// // warning: return new Bunny directly will leak memory! /// return TfCreateRefPtr(new Bunny); /// } /// static BunnyRefPtr New(bool isRabid) { /// return TfCreateRefPtr(new Bunny(isRabid)); /// } /// /// ~Bunny(); /// /// bool IsHungry(); /// private: /// Bunny(); /// Bunny(bool); /// }; /// /// BunnyRefPtr nice = Bunny::New(); /// BunnyRefPtr mean = Bunny::New(true); // this one is rabid /// /// BunnyRefPtr mean2 = mean; // two references to mean rabbit /// mean.Reset(); // one reference to mean rabbit /// /// if (mean2->IsHungry()) /// nice.Reset(); // nice bunny gone now... /// /// // this function comes from /// // TfRefBase; meaning is that /// if (mean2->IsUnique()) // mean2 is the last pointer to /// mean2.Reset(); // this bunny... /// \endcode /// /// Pretty much any pointer operation that is legal with regular pointers /// is legal with the \c BunnyRefPtr; continue reading for a more detailed /// description. /// /// Note that by virtue of deriving from \c TfRefBase, the reference /// count can be queried: see \c TfRefBase for details. /// /// \anchor refPtr_DetailedDiscussion /// Detailed Discussion: Overview /// /// Objects created by the \c new operator can easily be a source of /// both memory leaks and dangling pointers. One solution is /// \e reference counting; when an object is created by \c new, /// the number of pointers given the object's address is continually /// tracked in a \e reference \e counter. Then, \c delete is called on /// the object \e only when the object's reference count drops to zero, /// meaning there are no more pointers left pointing to the object. /// Reference counting avoids both dangling pointers and memory leaks. /// /// Access by regular pointers does not perform reference counting, but /// the \c TfRefPtr class implements reference-counted pointer access /// to objects of type \c T, with minimal overhead. The reference counting /// is made thread-safe by use of atomic integers. /// /// /// Basic Use /// /// The use of a \c TfRefPtr is simple. Whenever a \c TfRefPtr is /// made to point at an object, either by initialization or assignment, /// the object being pointed at has its reference count incremented. /// When a \c TfRefPtr with a non-NULL address is reassigned, or /// goes out of scope, the object being pointed to has its reference /// count decremented. /// /// A \c TfRefPtr can access \c T's public members by the /// \c -> operator and can be dereferenced by the "\c *" operator. /// Here is a simple example: /// \code /// #include "pxr/base/tf/refPtr.h" /// /// typedef TfRefPtr SimpleRefPtr; /// /// class Simple : public TfRefBase { /// public: /// void Method1(); /// int Method2(); /// /// static SimpleRefPtr New() { /// return TfCreateRefPtr(new Simple); /// } /// private: /// Simple(); /// }; /// /// /// SimpleRefPtr p1; // p1 points to NULL /// SimpleRefPtr p2 = Simple::New(); // p2 points to new object A /// SimpleRefPtr p3 = Simple::New(); // p3 points to new object B /// /// p1->Method1(); // runtime error -- p1 is NULL /// p3 = p2; // object B is deleted /// p2->Method1(); // Method1 on object A /// int value = p3->Method2(); // Method2 on object A /// /// p2.Reset(); // only p3 still points at A /// p3 = p1; // object A is deleted /// /// if (...) { /// SimpleRefPtr p4 = Simple::New(); // p4 points to object C /// p4->Method1(); /// } // object C destroyed /// \endcode /// /// Note that \c Simple's constructor is private; this ensures that one /// can only get at a \c Simple through \c Simple::New(), which is careful /// to return a \c SimpleRefPtr. /// /// Note that it is often useful to have both const and non-const /// versions of \c TfRefPtr for the same data type. Our convention /// is to use a \c typedef for each of these, with the const version /// beginning with "Const", after any prefix. The const version can be /// used as a parameter to a function in which you want to prevent /// changes to the pointed-to object. For example: /// \code /// typedef TfRefPtr XySimpleRefPtr; /// typedef TfRefPtr XyConstSimpleRefPtr; /// /// void /// Func1(const XySimpleRefPtr &p) /// { /// p->Modify(); // OK even if Modify() is not a const member /// } /// /// void /// Func2(const XyConstSimpleRefPtr &p) /// { /// p->Query(); // OK only if Query() is a const member /// } /// \endcode /// /// It is always possible to assign a non-const pointer to a const /// pointer variable. In extremely rare cases where you want to do the /// opposite, you can use the \c TfConst_cast function, as in: /// \code /// XyConstSimpleRefPtr p1; /// XySimpleRefPtr p2; /// /// p1 = p2; // OK /// p2 = p1; // Illegal! /// p2 = TfConst_cast(p1); // OK, but discouraged /// \endcode /// /// Comparisons and Tests /// /// Reference-counted pointers of like type can be compared; any \c TfRefPtr /// can be tested to see it is NULL or not: /// /// \code /// TfRefPtr elf = Elf::New(); /// TfRefPtr sleepy, /// sneezy = Dwarf::New(); /// /// if (!sleepy) /// ... // true: sleepy is NULL /// /// if (sneezy) /// ... // true: sneezy is non-nULL /// /// bool b1 = (sleepy != sneezy), /// b2 = (sleepy == sneezy), /// b3 = (elf == sneezy); // compilation error -- type clash /// /// \endcode /// /// Opaqueness /// /// A \c TfRefPtr can be used as an opaque pointer, just as a regular /// pointer can. For example, without having included the header file /// for a class \c XySimple, the following will still compile: /// \code /// #include "pxr/base/tf/refPtr.h" /// /// class XySimple; /// /// class Complicated { /// public: /// void SetSimple(const TfRefPtr& s) { /// _simplePtr = s; /// } /// /// TfRefPtr GetSimple() { /// return _simplePtr; /// } /// /// void Forget() { /// _simplePtr.Reset(); /// } /// /// private: /// TfRefPtr _simplePtr; /// }; /// \endcode /// /// Note that the call \c Forget() (or \c SetSimple() for that matter) /// may implicitly cause destruction of an \c XySimple object, if the count /// of the object pointed to by \c _simplePtr drops to zero. Even though /// the definition of \c XySimple is unknown, this compiles and works correctly. /// /// The only time that the definition of \c XySimple is required is when /// putting a raw \c XySimple* into a \c TfRefPtr; note however, that /// this should in fact only be done within the class definition of /// \c XySimple itself. /// /// Other cases that require a definition of \c XySimple are parallel to /// regular raw pointers, such as calling a member function, static or /// dynamic casts (but not const casts) and using the \c TfTypeid /// function. Transferring a \c TfWeakPtr to a \c TfRefPtr also /// requires knowing the definition of \c XySimple. /// /// Sometimes a class may have many typedefs associated with it, having /// to do with \c TfRefPtr or \c TfWeakPtr. If it is useful to use /// the class opaquely, we recommend creating a separate file /// as follows: /// /// \code /// // file: proj/xy/simplePtrDefs.h /// #include "pxr/base/tf/refPtr.h" /// #include "pxr/base/tf/weakPtr.h" /// /// typedef TfRefPtr XySimpleRefPtr; /// typedef TfRefPtr XyConstSimpleRefPtr; /// /// // typedefs for TfWeakPtr would follow, /// // if XySimple derives from TfWeakBase /// \endcode /// /// The definition for \c XySimple would then use the typedefs: /// /// \code /// #include "Proj/Xy/SimpleRefPtrDefs.h" /// /// class XySimple : public TfRefBase { /// public: /// static XySimpleRefPtr New(); /// ... /// }; /// /// \endcode /// /// The above pattern now allows a consumer of class \c XySimple the option /// to include only \c simplePtrDefs.h, if using the type opaquely suffices, /// or to include \c simple.h, if the class definition is required. /// /// /// Cyclic Dependencies /// /// If you build a tree using \c TfRefPtr, and you only have pointers /// from parent to child, everything is fine: if you "lose" the root of the /// tree, the tree will correctly destroy itself. /// /// But what if children point back to parents? Then a simple parent/child /// pair is stable, because the parent and child point at each other, and /// even if nobody else has a pointer to the parent, the reference count /// of the two nodes remains at one. /// /// The solution to this is to make one of the links (typically from child back /// to parent) use a \c TfWeakPtr. If a class \c T is enabled for both /// "guarding" (see \c TfWeakBase) and reference counting, then a \c TfRefPtr /// can be converted to a \c TfWeakPtr (in this context, a "back pointer") /// and vice versa. /// /// Inheritance /// /// /// Reference-counted pointers obey the same rules with respect to inheritance /// as regular pointers. In particular, if class \c Derived is derived /// from class \c Base, then the following are legal: /// /// \code /// TfRefPtr bPtr = new Base; /// TfRefPtr dPtr = new Derived; /// /// TfRefPtr b2Ptr = dPtr; // initialization /// b2Ptr = dPtr; // assignment /// b2Ptr == dPtr; // comparison /// /// dPtr = bPtr; // Not legal: compilation error /// \endcode /// /// As the last example shows, initialization or assignment to /// a \c TfRefPtr from a \c TfRefPtr is illegal, /// just as it is illegal to assign a \c Base* to a \c Derived*. /// However, if \c Derived and \c Base are polymorphic /// (i.e. have virtual functions) then the analogue of a \c dynamic_cast<> /// is possible: /// /// \code /// dPtr = TfDynamic_cast >(bPtr); /// \endcode /// /// Just like a regular \c dynamic_cast<> operation, the \c TfRefPtr /// returned by \c TfDynamic_cast<> points to NULL if the conversion fails, /// so that the operator can also be used to check types: /// /// \code /// if (! TfDynamic_cast >(ptr)) /// // complain: ptr is not of type T2 /// \endcode /// /// Similarly, one can use the \c TfStatic_cast<> operator to statically /// convert \c TfRefPtrs: /// /// \code /// dPtr = TfStatic_cast >(bPtr); /// \endcode /// /// This is faster, but not as safe as using \c TfDynamic_cast. /// /// Finally, remember that in \c C++, a \c Derived** is /// not a \c Base**, nor is a \c Derived*& a \c Base*&. This implies /// that /// /// \code /// TfRefPtr* bPtrPtr = &dPtr; // compilation error /// TfRefPtr& bPtrRef = dPtr; // compilation error /// const TfRefPtr&bPtrRef = dPtr; // OK /// \endcode /// /// The last initialization is legal because the compiler implicitly /// converts dPtr into a temporary variable of type \c TfRefPtr. /// /// /// Thread Safety /// /// One more comment about thread-safety: the above examples are thread-safe /// in the sense that if two or more threads create and destroy their \e own /// \c TfRefPtr objects, the reference counts of the underlying objects are /// always correct; said another way, the reference count it a thread-safe /// quantity. /// /// However, it is never safe for two threads to simultaneously try to alter /// the same \c TfRefPtr object, nor can two threads safely call methods on the /// same underlying object unless that object itself guarantees thread safety. /// /// \anchor refPtr_Tracking /// Tracking References /// /// The \c TfRefPtrTracker singleton can track \c TfRefPtr objects that /// point to particular instances. The macros \c TF_DECLARE_REFBASE_TRACK /// and \c TF_DEFINE_REFBASE_TRACK are used to enable tracking. Tracking /// is enabled at compile time but which instances to track is chosen at /// runtime. /// /// Total Encapsulation /// \anchor refPtr_encapsulation /// /// If you're using \c TfRefPtrs on a type \c T, you probably want /// to completely forbid clients from creating their own objects of /// type \c T, and force them to go through \c TfRefPtrs. Such /// encapsulation is strongly encouraged. Here is the recommended /// technique: /// /// \code /// /// typedef TfRefPtr SimpleRefPtr; /// /// class Simple : public TfRefBase { /// private: // use protected if you plan to derive later /// Simple(); /// Simple(); /// public: /// static SimpleRefPtr New() { /// return TfCreateRefPtr(new Simple); /// } /// /// static SimpleRefPtr New() { /// return TfCreateRefPtr(new Simple()); /// } /// /// ~Simple(); /// }; /// \endcode /// /// Clients can now only create objects of type \c Simple using a /// \c TfRefPtr: /// /// \code /// Simple s; // compilation error /// SimpleRefPtr sPtr1 = new Simple; // compilation error /// SimpleRefPtr sPtr2 = Simple::New(); // OK /// SimpleRefPtr sPtr3 = Simple::New(); // Ok /// \endcode /// #include "pxr/pxr.h" #include "pxr/base/tf/diagnosticLite.h" #include "pxr/base/tf/nullPtr.h" #include "pxr/base/tf/refBase.h" #include "pxr/base/tf/safeTypeCompare.h" #include "pxr/base/tf/typeFunctions.h" #include "pxr/base/tf/api.h" #include "pxr/base/arch/hints.h" #include #include #include #include #include #include #include #include #include PXR_NAMESPACE_OPEN_SCOPE // Tf_SupportsUniqueChanged is a metafunction that may be specialized to return // false for classes (and all derived classes) that *cannot* ever invoke unique // changed listeners. template struct Tf_SupportsUniqueChanged { static const bool Value = true; }; // Remnants are never able to support weak changed listeners. class Tf_Remnant; template <> struct Tf_SupportsUniqueChanged { static const bool Value = false; }; class TfWeakBase; template class TfWeakPtr; template