src/core/object.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 4472 e20a31541404
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) 2007 INRIA, Gustavo Carneiro
     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  * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
    19  *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    20  */
    21 #ifndef OBJECT_H
    22 #define OBJECT_H
    23 
    24 #include <stdint.h>
    25 #include <string>
    26 #include <vector>
    27 #include "ptr.h"
    28 #include "attribute.h"
    29 #include "object-base.h"
    30 #include "attribute-list.h"
    31 
    32 
    33 namespace ns3 {
    34 
    35 class Object;
    36 class AttributeAccessor;
    37 class AttributeValue;
    38 class AttributeList;
    39 class TraceSourceAccessor;
    40 
    41 /**
    42  * \ingroup core
    43  * \defgroup object Object
    44  */
    45 /**
    46  * \ingroup object
    47  * \brief a base class which provides memory management and object aggregation
    48  *
    49  * The memory management scheme is based on reference-counting with dispose-like
    50  * functionality to break the reference cycles. The reference count is increamented
    51  * and decremented with the methods Object::Ref and Object::Unref. If a reference cycle is
    52  * present, the user is responsible for breaking it by calling Object::Dispose in
    53  * a single location. This will eventually trigger the invocation of Object::DoDispose 
    54  * on itself and all its aggregates. The Object::DoDispose method is always automatically
    55  * invoked from the Object::Unref method before destroying the object, even if the user 
    56  * did not call Object::Dispose directly.
    57  */
    58 class Object : public ObjectBase
    59 {
    60 public:
    61   static TypeId GetTypeId (void);
    62 
    63   /**
    64    * \brief Iterate over the objects aggregated to an ns3::Object.
    65    *
    66    * This iterator does not allow you to iterate over the initial
    67    * object used to call Object::GetAggregateIterator. 
    68    *
    69    * Note: this is a java-style iterator.
    70    */
    71   class AggregateIterator
    72   {
    73   public:
    74     AggregateIterator ();
    75 
    76     /**
    77      * \returns true if HasNext can be called and return a non-null
    78      *          pointer, false otherwise.
    79      */
    80     bool HasNext (void) const;
    81 
    82     /**
    83      * \returns the next aggregated object.
    84      */
    85     Ptr<const Object> Next (void);
    86   private:
    87     friend class Object;
    88     AggregateIterator (Ptr<const Object> first);
    89     Ptr<const Object> m_first;
    90     Ptr<const Object> m_current;
    91   };
    92 
    93   Object ();
    94   virtual ~Object ();
    95 
    96   /*
    97    * Implement the GetInstanceTypeId method defined in ObjectBase.
    98    */
    99   virtual TypeId GetInstanceTypeId (void) const;
   100 
   101   /**
   102    * Increment the reference count. This method should not be called
   103    * by user code. Object instances are expected to be used in conjunction
   104    * of the Ptr template which would make calling Ref unecessary and 
   105    * dangerous.
   106    */
   107   inline void Ref (void) const;
   108   /**
   109    * Decrement the reference count. This method should not be called
   110    * by user code. Object instances are expected to be used in conjunction
   111    * of the Ptr template which would make calling Ref unecessary and 
   112    * dangerous.
   113    */
   114   inline void Unref (void) const;
   115 
   116   /**
   117    * Get the reference count of the object.  Normally not needed; for language bindings.
   118    */
   119   uint32_t GetReferenceCount (void) const;
   120 
   121   /**
   122    * \returns a pointer to the requested interface or zero if it could not be found.
   123    */
   124   template <typename T>
   125   Ptr<T> GetObject (void) const;
   126   /**
   127    * \param tid the interface id of the requested interface
   128    * \returns a pointer to the requested interface or zero if it could not be found.
   129    */
   130   template <typename T>
   131   Ptr<T> GetObject (TypeId tid) const;
   132   /**
   133    * Run the DoDispose methods of this object and all the
   134    * objects aggregated to it.
   135    * After calling this method, the object is expected to be
   136    * totally unusable except for the Ref and Unref methods.
   137    * It is an error to call Dispose twice on the same object 
   138    * instance.
   139    *
   140    * This method is typically used to break reference cycles.
   141    */
   142   void Dispose (void);
   143   /**
   144    * \param other another object pointer
   145    *
   146    * This method aggregates the two objects together: after this
   147    * method returns, it becomes possible to call GetObject
   148    * on one to get the other, and vice-versa. 
   149    */
   150   void AggregateObject (Ptr<Object> other);
   151 
   152   /**
   153    * \returns an iterator to the first object aggregated to this
   154    *          object.
   155    *
   156    * If no objects are aggregated to this object, then, the returned
   157    * iterator will be empty and AggregateIterator::HasNext will
   158    * always return false.
   159    */
   160   AggregateIterator GetAggregateIterator (void) const;
   161 
   162 protected:
   163  /**
   164   * This function is called by the AggregateObject on all the objects connected in the listed chain.
   165   * This way the new object aggregated will be used if needed by the NotifyNewAggregate corresponding
   166   * to each object connected in the listed chain. It should be implemented by objects needing an
   167   * additional/special behavior when aggregated to another object.
   168   */
   169   virtual void NotifyNewAggregate ();
   170   /**
   171    * This method is called by Object::Dispose or by the object's 
   172    * destructor, whichever comes first.
   173    *
   174    * Subclasses are expected to implement their real destruction
   175    * code in an overriden version of this method and chain
   176    * up to their parent's implementation once they are done.
   177    * i.e., for simplicity, the destructor of every subclass should
   178    * be empty and its content should be moved to the associated
   179    * DoDispose method.
   180    */
   181   virtual void DoDispose (void);
   182   /**
   183    * \param o the object to copy.
   184    *
   185    * Allow subclasses to implement a copy constructor.
   186    * While it is technically possible to implement a copy
   187    * constructor in a subclass, we strongly discourage you
   188    * to do so. If you really want to do it anyway, you have
   189    * to understand that this copy constructor will _not_
   190    * copy aggregated objects. i.e., if your object instance
   191    * is already aggregated to another object and if you invoke
   192    * this copy constructor, the new object instance will be
   193    * a pristine standlone object instance not aggregated to
   194    * any other object. It is thus _your_ responsability
   195    * as a caller of this method to do what needs to be done
   196    * (if it is needed) to ensure that the object stays in a
   197    * valid state.
   198    */
   199   Object (const Object &o);
   200 private:
   201 
   202   template <typename T>
   203   friend Ptr<T> CreateObjectWithAttributes (const AttributeList &attributes);
   204   template <typename T>
   205   friend Ptr<T> CopyObject (Ptr<T> object);
   206   template <typename T>
   207   friend Ptr<T> CopyObject (Ptr<const T> object);
   208   // The following friend method declaration is used only
   209   // by our python bindings to call the protected ObjectBase::Construct
   210   // method.
   211   friend void PythonCompleteConstruct (Ptr<Object> object, TypeId typeId, const AttributeList &attributes);
   212   template <typename T>
   213   friend Ptr<T> CompleteConstruct (T *object);
   214 
   215   friend class ObjectFactory;
   216   friend class AggregateIterator;
   217 
   218   Ptr<Object> DoGetObject (TypeId tid) const;
   219   bool Check (void) const;
   220   bool CheckLoose (void) const;
   221   /**
   222    * Attempt to delete this object. This method iterates
   223    * over all aggregated objects to check if they all 
   224    * have a zero refcount. If yes, the object and all
   225    * its aggregates are deleted. If not, nothing is done.
   226    */
   227   void MaybeDelete (void) const;
   228   /**
   229    * \param tid an TypeId
   230    *
   231    * Invoked from ns3::CreateObject only.
   232    * Initialize the m_tid member variable to
   233    * keep track of the type of this object instance.
   234    */
   235   void SetTypeId (TypeId tid);
   236    /**
   237    * \param attributes the attribute values used to initialize 
   238    *        the member variables of this object's instance.
   239    *
   240    * Invoked from ns3::ObjectFactory::Create and ns3::CreateObject only.
   241    * Initialize all the member variables which were
   242    * registered with the associated TypeId.
   243    */
   244   void Construct (const AttributeList &attributes);
   245 
   246   /**
   247    * The reference count for this object. Each aggregate
   248    * has an individual reference count. When the global
   249    * reference count (the sum of all reference counts) 
   250    * reaches zero, the object and all its aggregates is 
   251    * deleted.
   252    */
   253   mutable uint32_t m_count;
   254   /**
   255    * Identifies the type of this object instance.
   256    */
   257   TypeId m_tid;
   258   /**
   259    * Set to true when the DoDispose method of the object
   260    * has run, false otherwise.
   261    */
   262   bool m_disposed;
   263   /**
   264    * A pointer to the next aggregate object. This is a circular
   265    * linked list of aggregated objects: the last one points
   266    * back to the first one. If an object is not aggregated to
   267    * any other object, the value of this field is equal to the
   268    * value of the 'this' pointer.
   269    */
   270   Object *m_next;
   271 };
   272 
   273 /**
   274  * \param object a pointer to the object to copy.
   275  * \returns a copy of the input object.
   276  *
   277  * This method invoke the copy constructor of the input object
   278  * and returns the new instance.
   279  */
   280 template <typename T>
   281 Ptr<T> CopyObject (Ptr<const T> object);
   282 template <typename T>
   283 Ptr<T> CopyObject (Ptr<T> object);
   284 
   285 
   286 /**
   287  * \param attributes a list of attributes to set on the 
   288  *        object during construction.
   289  * \returns a pointer to a newly allocated object.
   290  *
   291  * This allocates an object on the heap and initializes
   292  * it with a set of attributes.
   293  */
   294 template <typename T>
   295 Ptr<T> CreateObjectWithAttributes (const AttributeList &attributes);
   296 
   297 /**
   298  * \param n1 name of attribute
   299  * \param v1 value of attribute
   300  * \param n2 name of attribute
   301  * \param v2 value of attribute
   302  * \param n3 name of attribute
   303  * \param v3 value of attribute
   304  * \param n4 name of attribute
   305  * \param v4 value of attribute
   306  * \param n5 name of attribute
   307  * \param v5 value of attribute
   308  * \param n6 name of attribute
   309  * \param v6 value of attribute
   310  * \param n7 name of attribute
   311  * \param v7 value of attribute
   312  * \param n8 name of attribute
   313  * \param v8 value of attribute
   314  * \param n9 name of attribute
   315  * \param v9 value of attribute
   316  * \returns a pointer to a newly allocated object.
   317  *
   318  * This allocates an object on the heap and initializes
   319  * it with a set of attributes.
   320  */
   321 template <typename T>
   322 Ptr<T> 
   323 CreateObjectWithAttributes (std::string n1 = "", const AttributeValue & v1 = EmptyAttributeValue (),
   324               std::string n2 = "", const AttributeValue & v2 = EmptyAttributeValue (),
   325               std::string n3 = "", const AttributeValue & v3 = EmptyAttributeValue (),
   326               std::string n4 = "", const AttributeValue & v4 = EmptyAttributeValue (),
   327               std::string n5 = "", const AttributeValue & v5 = EmptyAttributeValue (),
   328               std::string n6 = "", const AttributeValue & v6 = EmptyAttributeValue (),
   329               std::string n7 = "", const AttributeValue & v7 = EmptyAttributeValue (),
   330               std::string n8 = "", const AttributeValue & v8 = EmptyAttributeValue (),
   331               std::string n9 = "", const AttributeValue & v9 = EmptyAttributeValue ());
   332   
   333 
   334 
   335 } // namespace ns3
   336 
   337 namespace ns3 {
   338 
   339 /*************************************************************************
   340  *   The Object implementation which depends on templates
   341  *************************************************************************/
   342 
   343 void
   344 Object::Ref (void) const
   345 {
   346   m_count++;
   347 }
   348 void
   349 Object::Unref (void) const
   350 {
   351   NS_ASSERT (Check ());
   352   m_count--;
   353   if (m_count == 0)
   354     {
   355       MaybeDelete ();
   356     }
   357 }
   358 
   359 template <typename T>
   360 Ptr<T> 
   361 Object::GetObject () const
   362 {
   363   Ptr<Object> found = DoGetObject (T::GetTypeId ());
   364   if (found != 0)
   365     {
   366       return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
   367     }
   368   return 0;
   369 }
   370 
   371 template <typename T>
   372 Ptr<T> 
   373 Object::GetObject (TypeId tid) const
   374 {
   375   Ptr<Object> found = DoGetObject (tid);
   376   if (found != 0)
   377     {
   378       return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
   379     }
   380   return 0;
   381 }
   382 
   383 /*************************************************************************
   384  *   The helper functions which need templates.
   385  *************************************************************************/
   386 
   387 template <typename T>
   388 Ptr<T> CopyObject (Ptr<T> object)
   389 {
   390   Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
   391   NS_ASSERT (p->GetInstanceTypeId () == object->GetInstanceTypeId ());
   392   return p;
   393 }
   394 
   395 template <typename T>
   396 Ptr<T> CopyObject (Ptr<const T> object)
   397 {
   398   Ptr<T> p = Ptr<T> (new T (*PeekPointer (object)), false);
   399   NS_ASSERT (p->GetInstanceTypeId () == object->GetInstanceTypeId ());
   400   return p;
   401 }
   402 
   403 template <typename T>
   404 Ptr<T> CompleteConstruct (T *p)
   405 {
   406   p->SetTypeId (T::GetTypeId ());
   407   p->Object::Construct (AttributeList());
   408   return Ptr<T> (p, false);
   409 }
   410 template <typename T>
   411 Ptr<T> CreateObjectWithAttributes (const AttributeList &attributes)
   412 {
   413   Ptr<T> p = Ptr<T> (new T (), false);
   414   p->SetTypeId (T::GetTypeId ());
   415   p->Object::Construct (attributes);
   416   return p;  
   417 }
   418 
   419 template <typename T>
   420 Ptr<T> 
   421 CreateObjectWithAttributes (std::string n1 , const AttributeValue & v1,
   422               std::string n2 , const AttributeValue & v2,
   423               std::string n3 , const AttributeValue & v3,
   424               std::string n4 , const AttributeValue & v4,
   425               std::string n5 , const AttributeValue & v5,
   426               std::string n6 , const AttributeValue & v6,
   427               std::string n7 , const AttributeValue & v7,
   428               std::string n8 , const AttributeValue & v8,
   429               std::string n9 , const AttributeValue & v9)
   430 {
   431   AttributeList attributes;
   432   if (n1 == "")
   433     {
   434       goto end;
   435     }
   436   attributes.SetWithTid (T::GetTypeId (), n1, v1);
   437   if (n2 == "")
   438     {
   439       goto end;
   440     }
   441   attributes.SetWithTid (T::GetTypeId (), n2, v2);
   442   if (n3 == "")
   443     {
   444       goto end;
   445     }
   446   attributes.SetWithTid (T::GetTypeId (), n3, v3);
   447   if (n4 == "")
   448     {
   449       goto end;
   450     }
   451   attributes.SetWithTid (T::GetTypeId (), n4, v4);
   452   if (n5 == "")
   453     {
   454       goto end;
   455     }
   456   attributes.SetWithTid (T::GetTypeId (), n5, v5);
   457   if (n6 == "")
   458     {
   459       goto end;
   460     }
   461   attributes.SetWithTid (T::GetTypeId (), n6, v6);
   462   if (n7 == "")
   463     {
   464       goto end;
   465     }
   466   attributes.SetWithTid (T::GetTypeId (), n7, v7);
   467   if (n8 == "")
   468     {
   469       goto end;
   470     }
   471   attributes.SetWithTid (T::GetTypeId (), n8, v8);
   472   if (n9 == "")
   473     {
   474       goto end;
   475     }
   476   attributes.SetWithTid (T::GetTypeId (), n9, v9);
   477  end:
   478   return CreateObjectWithAttributes<T> (attributes);
   479 }
   480 
   481 template <typename T>
   482 Ptr<T> CreateObject (void)
   483 {
   484   return CompleteConstruct (new T ());
   485 }
   486 
   487 template <typename T, typename T1>
   488 Ptr<T> CreateObject (T1 a1)
   489 {
   490   return CompleteConstruct (new T (a1));
   491 }
   492 
   493 template <typename T, typename T1, typename T2>
   494 Ptr<T> CreateObject (T1 a1, T2 a2)
   495 {
   496   return CompleteConstruct (new T (a1,a2));
   497 }
   498 
   499 template <typename T, typename T1, typename T2, typename T3>
   500 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3)
   501 {
   502   return CompleteConstruct (new T (a1,a2,a3));
   503 }
   504 
   505 template <typename T, typename T1, typename T2, typename T3, typename T4>
   506 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
   507 {
   508   return CompleteConstruct (new T (a1,a2,a3,a4));
   509 }
   510 
   511 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
   512 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
   513 {
   514   return CompleteConstruct (new T (a1,a2,a3,a4,a5));
   515 }
   516 
   517 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
   518 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
   519 {
   520   return CompleteConstruct (new T (a1,a2,a3,a4,a5,a6));
   521 }
   522 
   523 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   524 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
   525 {
   526   return CompleteConstruct (new T (a1,a2,a3,a4,a5,a6,a7));
   527 }
   528 
   529 
   530 } // namespace ns3
   531 
   532 #endif /* OBJECT_H */
   533