From 63040fc74e1efa7a0702856ae28c7301b5ebecec Mon Sep 17 00:00:00 2001 From: "Peter D. Barnes, Jr." Date: Sun, 7 Dec 2014 18:30:55 -0800 Subject: [PATCH] [Doxygen] Smart pointers --- src/core/examples/main-ptr.cc | 27 ++ src/core/model/default-deleter.h | 20 +- src/core/model/ptr.h | 425 +++++++++++++++++++++++++----- src/core/model/simple-ref-count.h | 26 +- 4 files changed, 426 insertions(+), 72 deletions(-) diff --git a/src/core/examples/main-ptr.cc b/src/core/examples/main-ptr.cc index 36f444eeb..a4507a61a 100644 --- a/src/core/examples/main-ptr.cc +++ b/src/core/examples/main-ptr.cc @@ -21,13 +21,25 @@ #include "ns3/object.h" #include +/** + * \ingroup ptr + * \file + * Example program illustrating use of the ns3::Ptr smart pointer. + */ + using namespace ns3; +/** + * Example class illustrating use of Ptr. + */ class PtrExample : public Object { public: + /** Constructor. */ PtrExample (); + /** Destructor. */ ~PtrExample (); + /** Example class method. */ void Method (void); }; PtrExample::PtrExample () @@ -44,8 +56,20 @@ PtrExample::Method (void) std::cout << "PtrExample method" << std::endl; } + +/** + * Example Ptr global variable. + */ static Ptr g_ptr = 0; +/** + * Example Ptr manipulations. + * + * This function stores it's argument in the global variable \c g_ptr + * and returns the old value of \c g_ptr. + * \param [in] p A Ptr. + * \returns The prior value of \c g_ptr. + */ static Ptr StorePtr (Ptr p) { @@ -54,6 +78,9 @@ StorePtr (Ptr p) return prev; } +/** + * Set \c g_ptr to NULL. + */ static void ClearPtr (void) { diff --git a/src/core/model/default-deleter.h b/src/core/model/default-deleter.h index d7d57e497..a4662e6a5 100644 --- a/src/core/model/default-deleter.h +++ b/src/core/model/default-deleter.h @@ -20,19 +20,35 @@ #ifndef DEFAULT_DELETER_H #define DEFAULT_DELETER_H +/** + * \file + * \ingroup ptr + * Default deletion implementation for reference-counted smart pointers. + */ + namespace ns3 { /** - * \brief a template used to delete objects - * by the *RefCount<> templates when the + * \ingroup ptr + * \brief A template used to delete objects + * by the ns3::SimpleRefCount templates when the * last reference to an object they manage * disappears. * + * \tparam T The object type being deleted. * \sa ns3::SimpleRefCount */ template struct DefaultDeleter { + /** + * The default deleter implementation, which just does a normal + * \code + * delete object; + * \endcode + * \tparam T The object type being deleted. + * \param [in] object The object to delete. + */ inline static void Delete (T *object) { delete object; } diff --git a/src/core/model/ptr.h b/src/core/model/ptr.h index 132b2ca59..c161c6e6e 100644 --- a/src/core/model/ptr.h +++ b/src/core/model/ptr.h @@ -25,181 +25,449 @@ #include #include "assert.h" +/** + * \file + * \ingroup ptr + * Smart pointer implementation. + */ + namespace ns3 { /** * \ingroup core * \defgroup ptr Smart Pointer * \brief Heap memory management. + * + * See \ref ns3::Ptr for implementation details. + * + * See \ref main-ptr.cc for example usage. */ /** * \ingroup ptr * - * \brief smart pointer class similar to boost::intrusive_ptr + * \brief Smart pointer class similar to \c boost::intrusive_ptr. * * This smart-pointer class assumes that the underlying - * type provides a pair of Ref and Unref methods which are - * expected to increment and decrement the internal refcount - * of the object instance. + * type provides a pair of \c Ref and \c Unref methods which are + * expected to increment and decrement the internal reference count + * of the object instance. You can add \c Ref and \c Unref + * to a class simply by inheriting from ns3::SimpleRefCount. * * This implementation allows you to manipulate the smart pointer * as if it was a normal pointer: you can compare it with zero, * compare it against other pointers, assign zero to it, etc. * * It is possible to extract the raw pointer from this - * smart pointer with the GetPointer and PeekPointer methods. + * smart pointer with the GetPointer() and PeekPointer() methods. * - * If you want to store a newed object into a smart pointer, - * we recommend you to use the Create template functions + * If you want to store a \c new object into a smart pointer, + * we recommend you to use the Create() template functions * to create the object and store it in a smart pointer to avoid * memory leaks. These functions are really small convenience * functions and their goal is just is save you a small * bit of typing. + * + * \tparam T The underlying type. */ template class Ptr { private: + + /** The pointer. */ T *m_ptr; + + /** Helper to test for null pointer. */ class Tester { -private: + private: + /** Disable delete (by virtue that this is unimplemented). */ void operator delete (void *); }; + + /** Interoperate with const instances. */ friend class Ptr; + + /** + * Get a permanent pointer to the underlying object. + * + * The underlying refcount is incremented prior + * to returning to the caller so the caller is + * responsible for calling Unref himself. + * + * \param p smart pointer + * \return the pointer managed by this smart pointer. + */ template friend U *GetPointer (const Ptr &p); + /** + * Get a temporary pointer to the underlying object. + * + * The underlying refcount is not incremented prior + * to returning to the caller so the caller is not + * responsible for calling Unref himself. + * + * \param p smart pointer + * \return the pointer managed by this smart pointer. + */ template friend U *PeekPointer (const Ptr &p); + /** Mark this as a a reference by incrementing the reference count. */ inline void Acquire (void) const; + public: - /** - * Create an empty smart pointer - */ + /** Create an empty smart pointer */ Ptr (); /** - * \param ptr raw pointer to manage - * * Create a smart pointer which points to the object pointed to by * the input raw pointer ptr. This method creates its own reference * to the pointed object. The caller is responsible for Unref()'ing * its own reference, and the smart pointer will eventually do the * same, so that object is deleted if no more references to it * remain. + * + * \param ptr raw pointer to manage */ Ptr (T *ptr); /** + * Create a smart pointer which points to the object pointed to by + * the input raw pointer ptr. + * * \param ptr raw pointer to manage * \param ref if set to true, this method calls Ref, otherwise, * it does not call Ref. - * - * Create a smart pointer which points to the object pointed to by - * the input raw pointer ptr. */ Ptr (T *ptr, bool ref); + /** + * Copy by referencing the same underlying object. + * + * \param [in] o The other Ptr instance. + */ Ptr (Ptr const&o); - // allow conversions from T to T const. + /** + * Copy, removing \c const qualifier. + * + * \tparam U The underlying type of the \c const object. + * \param [in] o The Ptr to copy. + */ template - Ptr (Ptr const &o); + Ptr (Ptr const &o); + /** Destructor. */ ~Ptr (); + /** + * Assignment operator by referencing the same underlying object. + * + * \param [in] o The other Ptr instance. + * \return A reference to self. + */ Ptr &operator = (Ptr const& o); - + /** + * An rvalue member access. + * \returns A pointer to the underlying object. + */ T *operator -> () const; + /** + * An lvalue member access. + * \returns A pointer to the underlying object. + */ T *operator -> (); + /** + * A \c const dereference. + * \returns A pointer to the underlying object. + */ const T &operator * () const; + /** + * A dereference. + * \returns A pointer to the underlying object. + */ T &operator * (); - // allow if (!sp) + /** + * Test for NULL pointer. + * + * This enables simple NULL pointer checks like + * \code + * Ptr<..> p = ...; + * if (!p) ... + * \endcode + * \returns true if the underlying pointer is NULL. + */ bool operator! (); - // allow if (sp) - // disable delete sp + /** + * Test for non-NULL pointer. + * + * This enables simple pointer checks like + * \code + * Ptr<...> p = ...; + * if (p) ... + * \endcode + * This also disables deleting a Ptr + */ operator Tester * () const; }; +/** + * \ingroup ptr + * Create class instances by constructors with varying numbers + * of arguments and return them by Ptr. + * + * These methods work for any class \c T. + * + * \see CreateObject for methods to create derivatives of ns3::Object + */ +/** @{ */ +/** + * \tparam T The type of class object to create. + * \return A Ptr to the newly created \c T. + */ template Ptr Create (void); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \param a1 The first constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \tparam T3 The type of the third constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \param a3 The third constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2, T3 a3); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \tparam T3 The type of the third constructor argument. + * \tparam T4 The type of the fourth constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \param a3 The third constructor argument. + * \param a4 The fourth constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \tparam T3 The type of the third constructor argument. + * \tparam T4 The type of the fourth constructor argument. + * \tparam T5 The type of the fifth constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \param a3 The third constructor argument. + * \param a4 The fourth constructor argument. + * \param a5 The fifth constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \tparam T3 The type of the third constructor argument. + * \tparam T4 The type of the fourth constructor argument. + * \tparam T5 The type of the fifth constructor argument. + * \tparam T6 The type of the sixth constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \param a3 The third constructor argument. + * \param a4 The fourth constructor argument. + * \param a5 The fifth constructor argument. + * \param a6 The sixth constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6); -template +/** + * \tparam T The type of class object to create. + * \tparam T1 The type of the first constructor argument. + * \tparam T2 The type of the second constructor argument. + * \tparam T3 The type of the third constructor argument. + * \tparam T4 The type of the fourth constructor argument. + * \tparam T5 The type of the fifth constructor argument. + * \tparam T6 The type of the sixth constructor argument. + * \tparam T7 The type of the seventh constructor argument. + * \param a1 The first constructor argument. + * \param a2 The second constructor argument. + * \param a3 The third constructor argument. + * \param a4 The fourth constructor argument. + * \param a5 The fifth constructor argument. + * \param a6 The sixth constructor argument. + * \param a7 The seventh constructor argument. + * \return A Ptr to the newly created \c T. + */ +template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7); +/** @}*/ /** - * \relates Ptr - * \param p smart pointer - * \return the pointer managed by this smart pointer. - * - * The underlying refcount is not incremented prior - * to returning to the caller so the caller is not - * responsible for calling Unref himself. + * \ingroup ptr + * Output streamer. + * \param [in] os The output stream. + * \param [in] p The Ptr. + * \returns The stream. */ template -T * PeekPointer (const Ptr &p); +std::ostream &operator << (std::ostream &os, const Ptr &p); /** - * \relates Ptr - * \param p smart pointer - * \return the pointer managed by this smart pointer. + * \ingroup ptr + * Equality operator. * - * The underlying refcount is incremented prior - * to returning to the caller so the caller is - * responsible for calling Unref himself. + * This enables code such as + * \code + * Ptr<...> p = ...; + * Ptr<...> q = ...; + * if (p == q) ... + * \endcode + * + * Note that either \c p or \c q could also be ordinary pointers + * to the underlying object. + * + * \tparam T1 Type of the object on the lhs. + * \tparam T2 Type of the object on the rhs. + * \param [in] lhs The left operand. + * \param [in] rhs The right operand. + * \return true if the operands point to the same underlying object. */ -template -T * GetPointer (const Ptr &p); - -template -std::ostream &operator << (std::ostream &, const Ptr &p); - - -// allow if (sp == 0) +/** @{ */ template bool operator == (Ptr const &lhs, T2 const *rhs); -// allow if (0 == sp) template bool operator == (T1 const *lhs, Ptr &rhs); -// allow if (sp != 0) +template +bool operator == (Ptr const &lhs, Ptr const &rhs); +/**@}*/ + +/** + * \ingroup ptr + * Inequality operator. + * + * This enables code such as + * \code + * Ptr<...> p = ...; + * Ptr<...> q = ...; + * if (p != q) ... + * \endcode + * + * Note that either \c p or \c q could also be ordinary pointers + * to the underlying object. + * + * \tparam T1 Type of the object on the lhs. + * \tparam T2 Type of the object on the rhs. + * \param [in] lhs The left operand. + * \param [in] rhs The right operand. + * \return true if the operands point to the same underlying object. + */ +/** @{ */ template bool operator != (Ptr const &lhs, T2 const *rhs); -// allow if (0 != sp) template bool operator != (T1 const *lhs, Ptr &rhs); -// allow if (sp0 == sp1) -template -bool operator == (Ptr const &lhs, Ptr const &rhs); - -// allow if (sp0 != sp1) template bool operator != (Ptr const &lhs, Ptr const &rhs); +/**@}*/ + +/** + * \ingroup ptr + * Comparison operator applied to the underlying pointers. + * + * \param [in] lhs The left operand. + * \param [in] rhs The right operand. + * \return The comparison on the underlying pointers. + */ +/** @{ */ +template +bool operator < (const Ptr &lhs, const Ptr &rhs); +template +bool operator <= (const Ptr &lhs, const Ptr &rhs); +template +bool operator > (const Ptr &lhs, const Ptr &rhs); +template +bool operator >= (const Ptr &lhs, const Ptr &rhs); +/** @} */ + +/** + * Return a copy of \c p with its stored pointer const casted from + * \c T2 to \c T1. + * + * \tparam T1 The type to return in a Ptr. + * \tparam T2 The type of the underlying object. + * \param p The original \c const Ptr. + * \return A non-const Ptr. + */ template Ptr const_pointer_cast (Ptr const&p); template struct CallbackTraits; +/** + * \ingroup makecallbackmemptr + * + * Trait class to convert a pointer into a reference, + * used by MemPtrCallBackImpl. + * + * This is the specialization for Ptr types. + * + * \tparam The base object type. + */ template struct CallbackTraits > { + /** + * \param p object pointer + * \return a reference to the object pointed to by p + */ static T & GetReference (Ptr const p) { return *PeekPointer (p); @@ -209,9 +477,21 @@ struct CallbackTraits > template struct EventMemberImplObjTraits; +/** + * \ingroup makeeventmemptr + * Helper for the MakeEvent functions which take a class method. + * + * This is the specialization for Ptr types. + * + * \tparam T The class type. + */ template struct EventMemberImplObjTraits > { + /** + * \param p object pointer + * \return a reference to the object pointed to by p + */ static T &GetReference (Ptr p) { return *PeekPointer (p); } @@ -276,14 +556,14 @@ Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) return Ptr (new T (a1, a2, a3, a4, a5, a6, a7), false); } -template -T * PeekPointer (const Ptr &p) +template +U * PeekPointer (const Ptr &p) { return p.m_ptr; } -template -T * GetPointer (const Ptr &p) +template +U * GetPointer (const Ptr &p) { p.Acquire (); return p.m_ptr; @@ -362,6 +642,15 @@ bool operator >= (const Ptr &lhs, const Ptr &rhs) return PeekPointer (lhs) >= PeekPointer (rhs); } +/** + * Cast a Ptr. + * + * \tparam T1 The desired type to cast to. + * \tparam T2 The type of the original Ptr. + * \param p The original Ptr. + * \return The result of the cast. + */ +/** @{ */ template Ptr ConstCast (Ptr const&p) @@ -382,8 +671,15 @@ StaticCast (Ptr const&p) { return Ptr (static_cast (PeekPointer (p))); } +/** @} */ - +/** + * Return a deep copy of a Ptr. + * + * \param object The object Ptr to copy. + * \returns The copy. + */ +/** @{ */ template Ptr Copy (Ptr object) { @@ -397,6 +693,7 @@ Ptr Copy (Ptr object) Ptr p = Ptr (new T (*PeekPointer (object)), false); return p; } +/** @} */ /**************************************************** * Member method implementations. diff --git a/src/core/model/simple-ref-count.h b/src/core/model/simple-ref-count.h index 55e54628b..06443a25f 100644 --- a/src/core/model/simple-ref-count.h +++ b/src/core/model/simple-ref-count.h @@ -28,6 +28,12 @@ #include #include +/** + * \file + * \ingroup ptr + * Reference counting for smart pointers. + */ + namespace ns3 { /** @@ -36,7 +42,7 @@ namespace ns3 { * * This template can be used to give reference-counting powers * to a class. This template does not require this class to - * have a virtual destructor or no parent class. + * have a virtual destructor or a specific (or any) parent class. * * Note: if you are moving to this template from the RefCountBase class, * you need to be careful to mark appropriately your destructor virtual @@ -46,14 +52,15 @@ namespace ns3 { * * This template takes 3 arguments but only the first argument is * mandatory: - * - T: the typename of the subclass which derives from this template + * + * \tparam T The typename of the subclass which derives from this template * class. Yes, this is weird but it's a common C++ template pattern * whose name is CRTP (Curiously Recursive Template Pattern) - * - PARENT: the typename of the parent of this template. By default, + * \tparam PARENT: the typename of the parent of this template. By default, * this typename is "'ns3::empty'" which is an empty class: compilers * which implement the RBCO optimization (empty base class optimization) * will make this a no-op - * - DELETER: the typename of a class which implements a public static + * \tparam DELETER: the typename of a class which implements a public static * method named 'Delete'. This method will be called whenever the * SimpleRefCount template detects that no references to the object * it manages exist anymore. @@ -112,6 +119,8 @@ public: /** * Get the reference count of the object. * Normally not needed; for language bindings. + * + * \return The reference count. */ inline uint32_t GetReferenceCount (void) const { @@ -123,8 +132,13 @@ public: */ static void Cleanup (void) {} private: - // Note we make this mutable so that the const methods can still - // change it. + /** + * The reference count. + * + * \internal + * Note we make this mutable so that the const methods can still + * change it. + */ mutable uint32_t m_count; };