/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2005,2006 INRIA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage */ #ifndef PTR_H #define PTR_H #include #include #include "assert.h" namespace ns3 { /** * \ingroup core * \defgroup ptr Smart Pointer */ /** * \ingroup ptr * * \brief smart pointer class similar to 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. * * 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. * * If you want to store a newed 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. */ template class Ptr { private: T *m_ptr; class Tester { private: void operator delete (void *); }; friend class Ptr; template friend U *GetPointer (const Ptr &p); template friend U *PeekPointer (const Ptr &p); inline void Acquire (void) const; public: /** * 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. */ Ptr (T *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); Ptr (Ptr const&o); // allow conversions from T to T const. template Ptr (Ptr const &o); ~Ptr (); Ptr &operator = (Ptr const& o); T *operator -> () const; T *operator -> (); const T &operator * () const; T &operator * (); // allow if (!sp) bool operator! (); // allow if (sp) // disable delete sp operator Tester * () const; }; template Ptr Create (void); template Ptr Create (T1 a1); template Ptr Create (T1 a1, T2 a2); template Ptr Create (T1 a1, T2 a2, T3 a3); template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4); template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6); 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. */ template T * PeekPointer (const Ptr &p); /** * \relates Ptr * \param p smart pointer * \return the pointer managed by this smart pointer. * * The underlying refcount is incremented prior * to returning to the caller so the caller is * responsible for calling Unref himself. */ 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, 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); template Ptr const_pointer_cast (Ptr const&p); template struct CallbackTraits; template struct CallbackTraits > { static T & GetReference (Ptr const p) { return *PeekPointer (p); } }; template struct EventMemberImplObjTraits; template struct EventMemberImplObjTraits > { static T &GetReference (Ptr p) { return *PeekPointer (p); } }; } // namespace ns3 namespace ns3 { /************************************************* * friend non-member function implementations ************************************************/ template Ptr Create (void) { return Ptr (new T (), false); } template Ptr Create (T1 a1) { return Ptr (new T (a1), false); } template Ptr Create (T1 a1, T2 a2) { return Ptr (new T (a1, a2), false); } template Ptr Create (T1 a1, T2 a2, T3 a3) { return Ptr (new T (a1, a2, a3), false); } template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4) { return Ptr (new T (a1, a2, a3, a4), false); } template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { return Ptr (new T (a1, a2, a3, a4, a5), false); } template Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { return Ptr (new T (a1, a2, a3, a4, a5, a6), false); } template 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) { return p.m_ptr; } template T * GetPointer (const Ptr &p) { p.Acquire (); return p.m_ptr; } template std::ostream &operator << (std::ostream &os, const Ptr &p) { os << PeekPointer (p); return os; } template bool operator == (Ptr const &lhs, T2 const *rhs) { return PeekPointer (lhs) == rhs; } template bool operator == (T1 const *lhs, Ptr &rhs) { return lhs == PeekPointer (rhs); } template bool operator != (Ptr const &lhs, T2 const *rhs) { return PeekPointer (lhs) != rhs; } template bool operator != (T1 const *lhs, Ptr &rhs) { return lhs != PeekPointer (rhs); } template bool operator == (Ptr const &lhs, Ptr const &rhs) { return PeekPointer (lhs) == PeekPointer (rhs); } template bool operator != (Ptr const &lhs, Ptr const &rhs) { return PeekPointer (lhs) != PeekPointer (rhs); } template bool operator < (const Ptr &lhs, const Ptr &rhs) { return PeekPointer (lhs) < PeekPointer (rhs); } template bool operator <= (const Ptr &lhs, const Ptr &rhs) { return PeekPointer (lhs) <= PeekPointer (rhs); } template bool operator > (const Ptr &lhs, const Ptr &rhs) { return PeekPointer (lhs) > PeekPointer (rhs); } template bool operator >= (const Ptr &lhs, const Ptr &rhs) { return PeekPointer (lhs) >= PeekPointer (rhs); } template Ptr ConstCast (Ptr const&p) { return Ptr (const_cast (PeekPointer (p))); } template Ptr DynamicCast (Ptr const&p) { return Ptr (dynamic_cast (PeekPointer (p))); } template Ptr StaticCast (Ptr const&p) { return Ptr (static_cast (PeekPointer (p))); } template Ptr Copy (Ptr object) { Ptr p = Ptr (new T (*PeekPointer (object)), false); return p; } template Ptr Copy (Ptr object) { Ptr p = Ptr (new T (*PeekPointer (object)), false); return p; } /**************************************************** * Member method implementations. ***************************************************/ template void Ptr::Acquire (void) const { if (m_ptr != 0) { m_ptr->Ref (); } } template Ptr::Ptr () : m_ptr (0) { } template Ptr::Ptr (T *ptr) : m_ptr (ptr) { Acquire (); } template Ptr::Ptr (T *ptr, bool ref) : m_ptr (ptr) { if (ref) { Acquire (); } } template Ptr::Ptr (Ptr const&o) : m_ptr (PeekPointer (o)) { Acquire (); } template template Ptr::Ptr (Ptr const &o) : m_ptr (PeekPointer (o)) { Acquire (); } template Ptr::~Ptr () { if (m_ptr != 0) { m_ptr->Unref (); } } template Ptr & Ptr::operator = (Ptr const& o) { if (&o == this) { return *this; } if (m_ptr != 0) { m_ptr->Unref (); } m_ptr = o.m_ptr; Acquire (); return *this; } template T * Ptr::operator -> () { return m_ptr; } template T * Ptr::operator -> () const { return m_ptr; } template const T & Ptr::operator * () const { return *m_ptr; } template T & Ptr::operator * () { return *m_ptr; } template bool Ptr::operator! () { return m_ptr == 0; } template Ptr::operator Tester * () const { if (m_ptr == 0) { return 0; } static Tester test; return &test; } } // namespace ns3 #endif /* PTR_H */