src/core/ptr.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3767 b03ea30335a3
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2005,2006 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 
    21 #ifndef PTR_H
    22 #define PTR_H
    23 
    24 #include <iostream>
    25 #include <stdint.h>
    26 #include "assert.h"
    27 
    28 namespace ns3 {
    29 
    30 /**
    31  * \ingroup core
    32  * \defgroup ptr Smart Pointer
    33  */
    34 /**
    35  * \ingroup ptr
    36  *
    37  * \brief smart pointer class similar to boost::intrusive_ptr
    38  *
    39  * This smart-pointer class assumes that the underlying
    40  * type provides a pair of Ref and Unref methods which are
    41  * expected to increment and decrement the internal refcount
    42  * of the object instance.
    43  *
    44  * This implementation allows you to manipulate the smart pointer
    45  * as if it was a normal pointer: you can compare it with zero,
    46  * compare it against other pointers, assign zero to it, etc.
    47  *
    48  * It is possible to extract the raw pointer from this
    49  * smart pointer with the GetPointer and PeekPointer methods.
    50  *
    51  * If you want to store a newed object into a smart pointer,
    52  * we recommend you to use the Create template functions
    53  * to create the object and store it in a smart pointer to avoid
    54  * memory leaks. These functions are really small conveniance
    55  * functions and their goal is just is save you a small
    56  * bit of typing.
    57  */
    58 template <typename T>
    59 class Ptr 
    60 {
    61 private:
    62   T *m_ptr;
    63   class Tester {
    64   private:
    65     void operator delete (void *);
    66   };
    67   friend class Ptr<const T>;
    68   template <typename U>
    69   friend U *GetPointer (const Ptr<U> &p);
    70   template <typename U>
    71   friend U *PeekPointer (const Ptr<U> &p);
    72 
    73   inline void Acquire (void) const;
    74 public:
    75   /**
    76    * Create an empty smart pointer
    77    */
    78   Ptr ();
    79   /**
    80    * \param ptr raw pointer to manage
    81    *
    82    * Create a smart pointer which points to the object pointed to by
    83    * the input raw pointer ptr. This method creates its own reference
    84    * to the pointed object. The caller is responsible for Unref()'ing
    85    * its own reference, and the smart pointer will eventually do the
    86    * same, so that object is deleted if no more references to it
    87    * remain.
    88    */
    89   Ptr (T *ptr);  
    90   /**
    91    * \param ptr raw pointer to manage
    92    * \param ref if set to true, this method calls Ref, otherwise,
    93    *        it does not call Ref.
    94    *    
    95    * Create a smart pointer which points to the object pointed to by
    96    * the input raw pointer ptr.
    97    */
    98   Ptr (T *ptr, bool ref);
    99   Ptr (Ptr const&o);
   100   // allow conversions from T to T const.
   101   template <typename U>
   102   Ptr (Ptr<U> const &o);
   103   ~Ptr () ;
   104   Ptr<T> &operator = (Ptr const& o);
   105 
   106   T *operator -> () const;
   107   T *operator -> ();
   108   const T &operator * () const;
   109   T &operator * ();
   110   // allow if (!sp)
   111   bool operator! ();
   112   // allow if (sp)
   113   // disable delete sp
   114   operator Tester * () const;
   115 };
   116 
   117 template <typename T>
   118 Ptr<T> Create (void);
   119 
   120 template <typename T, typename T1>
   121 Ptr<T> Create (T1 a1);
   122 
   123 template <typename T, typename T1, typename T2>
   124 Ptr<T> Create (T1 a1, T2 a2);
   125 
   126 template <typename T, typename T1, typename T2, typename T3>
   127 Ptr<T> Create (T1 a1, T2 a2, T3 a3);
   128 
   129 template <typename T, typename T1, typename T2, typename T3, typename T4>
   130 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4);
   131 
   132 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
   133 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   134 
   135 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
   136 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
   137 
   138 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   139 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
   140 
   141 /**
   142  * \relates Ptr
   143  * \return the pointer managed by this smart pointer.
   144  *
   145  * The underlying refcount is not incremented prior
   146  * to returning to the caller so the caller is not
   147  * responsible for calling Unref himself.
   148  */
   149 template <typename T>
   150 T * PeekPointer (const Ptr<T> &p);
   151 
   152 /**
   153  * \relates Ptr
   154  * \return the pointer managed by this smart pointer.
   155  *
   156  * The underlying refcount is incremented prior
   157  * to returning to the caller so the caller is
   158  * responsible for calling Unref himself.
   159  */
   160 template <typename T>
   161 T * GetPointer (const Ptr<T> &p);
   162 
   163 template <typename T>
   164 std::ostream &operator << (std::ostream &, const Ptr<T> &p);
   165 
   166 
   167 // allow if (sp == 0)
   168 template <typename T1, typename T2>
   169 bool operator == (Ptr<T1> const &lhs, T2 const *rhs);
   170 
   171 // allow if (0 == sp)
   172 template <typename T1, typename T2>
   173 bool operator == (T1 const *lhs, Ptr<T2> &rhs);
   174 
   175 // allow if (sp != 0)
   176 template <typename T1, typename T2>
   177 bool operator != (Ptr<T1> const &lhs, T2 const *rhs);
   178 
   179 // allow if (0 != sp)
   180 template <typename T1, typename T2>
   181 bool operator != (T1 const *lhs, Ptr<T2> &rhs);
   182 
   183 // allow if (sp0 == sp1)
   184 template <typename T1, typename T2>
   185 bool operator == (Ptr<T1> const &lhs, Ptr<T2> const &rhs);
   186 
   187 // allow if (sp0 != sp1)
   188 template <typename T1, typename T2>
   189 bool operator != (Ptr<T1> const &lhs, Ptr<T2> const &rhs);
   190 
   191 template <typename T1, typename T2>
   192 Ptr<T1> const_pointer_cast (Ptr<T2> const&p);
   193 
   194 template <typename T>
   195 struct CallbackTraits;
   196 
   197 template <typename T>
   198 struct CallbackTraits<Ptr<T> >
   199 {
   200   static T & GetReference (Ptr<T> const p)
   201   {
   202     return *PeekPointer (p);
   203   }
   204 };
   205 
   206 template <typename T>
   207 struct EventMemberImplObjTraits;
   208 
   209 template <typename T>
   210 struct EventMemberImplObjTraits<Ptr<T> >
   211 {
   212   static T &GetReference (Ptr<T> p) {
   213     return *PeekPointer (p);
   214   }
   215 };
   216 
   217 
   218 
   219 } // namespace ns3
   220 
   221 
   222 namespace ns3 {
   223 
   224   /*************************************************
   225    *  friend non-member function implementations
   226    ************************************************/
   227 
   228 template <typename T>
   229 Ptr<T> Create (void)
   230 {
   231   return Ptr<T> (new T (), false);
   232 }
   233 
   234 template <typename T, typename T1>
   235 Ptr<T> Create (T1 a1)
   236 {
   237   return Ptr<T> (new T (a1), false);
   238 }
   239 
   240 template <typename T, typename T1, typename T2>
   241 Ptr<T> Create (T1 a1, T2 a2)
   242 {
   243   return Ptr<T> (new T (a1, a2), false);
   244 }
   245 
   246 template <typename T, typename T1, typename T2, typename T3>
   247 Ptr<T> Create (T1 a1, T2 a2, T3 a3)
   248 {
   249   return Ptr<T> (new T (a1, a2, a3), false);
   250 }
   251 
   252 template <typename T, typename T1, typename T2, typename T3, typename T4>
   253 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4)
   254 {
   255   return Ptr<T> (new T (a1, a2, a3, a4), false);
   256 }
   257 
   258 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
   259 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
   260 {
   261   return Ptr<T> (new T (a1, a2, a3, a4, a5), false);
   262 }
   263 
   264 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
   265 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
   266 {
   267   return Ptr<T> (new T (a1, a2, a3, a4, a5, a6), false);
   268 }
   269 
   270 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   271 Ptr<T> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
   272 {
   273   return Ptr<T> (new T (a1, a2, a3, a4, a5, a6, a7), false);
   274 }
   275 
   276 template <typename T>
   277 T * PeekPointer (const Ptr<T> &p)
   278 {
   279   return p.m_ptr;
   280 }
   281 
   282 template <typename T>
   283 T * GetPointer (const Ptr<T> &p)
   284 {
   285   p.Acquire ();
   286   return p.m_ptr;
   287 }
   288 
   289 template <typename T>
   290 std::ostream &operator << (std::ostream &os, const Ptr<T> &p)
   291 {
   292   os << PeekPointer (p);
   293   return os;
   294 }
   295 
   296 template <typename T1, typename T2>
   297 bool 
   298 operator == (Ptr<T1> const &lhs, T2 const *rhs)
   299 {
   300   return PeekPointer (lhs) == rhs;
   301 }
   302 
   303 template <typename T1, typename T2>
   304 bool 
   305 operator == (T1 const *lhs, Ptr<T2> &rhs)
   306 {
   307   return lhs == PeekPointer (rhs);
   308 }
   309 
   310 template <typename T1, typename T2>
   311 bool 
   312 operator != (Ptr<T1> const &lhs, T2 const *rhs)
   313 {
   314   return PeekPointer (lhs) != rhs;
   315 }
   316 
   317 template <typename T1, typename T2>
   318 bool 
   319 operator != (T1 const *lhs, Ptr<T2> &rhs)
   320 {
   321   return lhs != PeekPointer (rhs);
   322 }
   323 
   324 template <typename T1, typename T2>
   325 bool 
   326 operator == (Ptr<T1> const &lhs, Ptr<T2> const &rhs)
   327 {
   328   return PeekPointer (lhs) == PeekPointer (rhs);
   329 }
   330 
   331 template <typename T1, typename T2>
   332 bool 
   333 operator != (Ptr<T1> const &lhs, Ptr<T2> const &rhs)
   334 {
   335   return PeekPointer (lhs) != PeekPointer (rhs);
   336 }
   337 
   338 template <typename T>
   339 bool operator < (const Ptr<T> &lhs, const Ptr<T> &rhs)
   340 {
   341   return PeekPointer<T> (lhs) < PeekPointer<T> (rhs);
   342 }
   343 
   344 template <typename T>
   345 bool operator <= (const Ptr<T> &lhs, const Ptr<T> &rhs)
   346 {
   347   return PeekPointer<T> (lhs) <= PeekPointer<T> (rhs);
   348 }
   349 
   350 template <typename T>
   351 bool operator > (const Ptr<T> &lhs, const Ptr<T> &rhs)
   352 {
   353   return PeekPointer<T> (lhs) > PeekPointer<T> (rhs);
   354 }
   355 
   356 template <typename T>
   357 bool operator >= (const Ptr<T> &lhs, const Ptr<T> &rhs)
   358 {
   359   return PeekPointer<T> (lhs) >= PeekPointer<T> (rhs);
   360 }
   361 
   362 template <typename T1, typename T2>
   363 Ptr<T1>
   364 ConstCast (Ptr<T2> const&p)
   365 {
   366   return Ptr<T1> (const_cast<T1 *> (PeekPointer (p)));
   367 }
   368 
   369 template <typename T1, typename T2>
   370 Ptr<T1>
   371 DynamicCast (Ptr<T2> const&p)
   372 {
   373   return Ptr<T1> (dynamic_cast<T1 *> (PeekPointer (p)));
   374 }
   375 
   376 
   377 /****************************************************
   378  *      Member method implementations.
   379  ***************************************************/
   380 
   381 template <typename T>
   382 void 
   383 Ptr<T>::Acquire (void) const
   384 {
   385   if (m_ptr != 0)
   386     {
   387       m_ptr->Ref ();
   388     }  
   389 }
   390 
   391 template <typename T>
   392 Ptr<T>::Ptr ()
   393   : m_ptr (0)
   394 {}
   395 
   396 template <typename T>
   397 Ptr<T>::Ptr (T *ptr) 
   398   : m_ptr (ptr)
   399 {
   400   Acquire ();
   401 }
   402 
   403 template <typename T>
   404 Ptr<T>::Ptr (T *ptr, bool ref) 
   405   : m_ptr (ptr)
   406 {
   407   if (ref)
   408     {
   409       Acquire ();
   410     }
   411 }
   412 
   413 template <typename T>
   414 Ptr<T>::Ptr (Ptr const&o) 
   415   : m_ptr (PeekPointer (o))
   416 {
   417   Acquire ();
   418 }
   419 template <typename T>
   420 template <typename U>
   421 Ptr<T>::Ptr (Ptr<U> const &o)
   422   : m_ptr (PeekPointer (o))
   423 {
   424   Acquire ();
   425 }
   426 
   427 template <typename T>
   428 Ptr<T>::~Ptr () 
   429 {
   430   if (m_ptr != 0) 
   431     {
   432       m_ptr->Unref();
   433     }
   434 }
   435 
   436 template <typename T>
   437 Ptr<T> &
   438 Ptr<T>::operator = (Ptr const& o) 
   439 {
   440   if (&o == this)
   441     {
   442       return *this;
   443     }
   444   if (m_ptr != 0) 
   445     {
   446       m_ptr->Unref();
   447     }
   448   m_ptr = o.m_ptr;
   449   Acquire ();
   450   return *this;
   451 }
   452 
   453 template <typename T>
   454 T *
   455 Ptr<T>::operator -> () 
   456 {
   457   return m_ptr;
   458 }
   459 
   460 template <typename T>
   461 T *
   462 Ptr<T>::operator -> () const
   463 {
   464   return m_ptr;
   465 }
   466 
   467 template <typename T>
   468 const T &
   469 Ptr<T>::operator * () const
   470 {
   471   return *m_ptr;
   472 }
   473 
   474 template <typename T>
   475 T &
   476 Ptr<T>::operator * ()
   477 {
   478   return *m_ptr;
   479 }
   480 
   481 template <typename T>
   482 bool 
   483 Ptr<T>::operator! () 
   484 {
   485   return m_ptr == 0;
   486 }
   487 
   488 template <typename T>
   489 Ptr<T>::operator Tester * () const
   490 {
   491   if (m_ptr == 0) 
   492     {
   493       return 0;
   494     }
   495   static Tester test;
   496   return &test;
   497 }
   498 
   499 
   500 }; // namespace ns3
   501 
   502 #endif /* PTR_H */