src/core/object.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 02 Mar 2008 21:00:37 +0100
changeset 2531 b451b5fc8b57
parent 2522 7c9d1c314beb
child 2542 a9b88fdc09d6
permissions -rw-r--r--
implement context-based trace connection
     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 "ptr.h"
    27 #include "trace-resolver.h"
    28 #include "callback.h"
    29 #include "attribute.h"
    30 #include "object-base.h"
    31 #include "attribute-helper.h"
    32 
    33 #define NS_OBJECT_ENSURE_REGISTERED(type)       \
    34   static struct X##type##RegistrationClass      \
    35   {                                             \
    36     X##type##RegistrationClass () {             \
    37       ns3::TypeId tid = type::GetTypeId ();     \
    38       tid.GetParent ();                         \
    39     }                                           \
    40 } x_##type##RegistrationVariable
    41 
    42 
    43 namespace ns3 {
    44 
    45 class TraceContext;
    46 class CallbackBase;
    47 class Object;
    48 class AttributeAccessor;
    49 class AttributeValue;
    50 class AttributeList;
    51 class TraceSourceAccessor;
    52 
    53 /**
    54  * \brief a unique identifier for an interface.
    55  *
    56  * This class records a lot of meta-information about a 
    57  * subclass of the Object base class:
    58  *  - the base class of the subclass
    59  *  - the set of accessible constructors in the subclass
    60  *  - the set of 'attributes' accessible in the subclass
    61  */
    62 class TypeId
    63 {
    64 public:
    65   enum {
    66     ATTR_GET = 1<<0,
    67     ATTR_SET = 1<<1,
    68     ATTR_CONSTRUCT = 1<<2,
    69     ATTR_SGC = ATTR_GET | ATTR_SET | ATTR_CONSTRUCT,
    70   };
    71 
    72   /**
    73    * \param name the name of the requested interface
    74    * \returns the unique id associated with the requested
    75    *          name. 
    76    *
    77    * This method cannot fail: it will crash if the input 
    78    * name is not a valid interface name.
    79    */
    80   static TypeId LookupByName (std::string name);
    81 
    82   /**
    83    * \returns the number of TypeId instances constructed
    84    */
    85   static uint32_t GetRegisteredN (void);
    86   /**
    87    * \param i index
    88    * \returns the TypeId instance whose index is \i.
    89    */
    90   static TypeId GetRegistered (uint32_t i);
    91 
    92   /**
    93    * \param name the name of the interface to construct.
    94    *
    95    * No two instances can share the same name.
    96    */
    97   TypeId (const char * name);
    98 
    99   /**
   100    * \returns the parent of this TypeId
   101    *
   102    * This method cannot fail. It will return itself
   103    * if this TypeId has no parent. i.e., it is at the top
   104    * of the TypeId hierarchy. Currently, this is the
   105    * case for the TypeId associated to the Object class 
   106    * only.
   107    */
   108   TypeId GetParent (void) const;
   109 
   110   /**
   111    * \returns the name of the group associated to this TypeId.
   112    */
   113   std::string GetGroupName (void) const;
   114   /**
   115    * \returns the fully-qualified C++ typename of this TypeId.
   116    */
   117   std::string GetTypeName (void) const;
   118 
   119   /**
   120    * \returns the name of this interface.
   121    */
   122   std::string GetName (void) const;
   123 
   124   /**
   125    * \returns true if this TypeId has a constructor
   126    */
   127   bool HasConstructor (void) const;
   128 
   129   /**
   130    * \returns the number of attributes associated to this TypeId
   131    */
   132   uint32_t GetAttributeListN (void) const;
   133   /**
   134    * \param i index into attribute array
   135    * \returns the name associated to the attribute whose
   136    *          index is \i i.
   137    */
   138   std::string GetAttributeName (uint32_t i) const;
   139   /**
   140    * \param i index into attribute array
   141    * \returns the full name associated to the attribute whose
   142    *          index is \i i.
   143    */
   144   std::string GetAttributeFullName (uint32_t i) const;
   145 
   146   Attribute GetAttributeInitialValue (uint32_t i) const;
   147 
   148   uint32_t GetTraceSourceN (void) const;
   149   std::string GetTraceSourceName (uint32_t i) const;
   150   std::string GetTraceSourceHelp (uint32_t i) const;
   151   Ptr<const TraceSourceAccessor> GetTraceSourceAccessor (uint32_t i) const;
   152 
   153   Ptr<Object> CreateObject (const AttributeList &attributes) const;
   154 
   155 
   156   Ptr<Object> CreateObject (void) const;
   157   template <typename T1>
   158   Ptr<Object> CreateObject (T1 a1) const;
   159   template <typename T1, typename T2>
   160   Ptr<Object> CreateObject (T1 a1, T2 a2) const;
   161 
   162 
   163   /**
   164    * \param tid the TypeId of the base class.
   165    * \return this TypeId instance.
   166    *
   167    * Record in this TypeId which TypeId is the TypeId
   168    * of the base class of the subclass.
   169    */
   170   TypeId SetParent (TypeId tid);
   171   /**
   172    * \return this TypeId instance.
   173    *
   174    * Record in this TypeId which TypeId is the TypeId
   175    * of the base class of the subclass.
   176    */
   177   template <typename T>
   178   TypeId SetParent (void);
   179 
   180   /**
   181    * \param groupName the name of the group this TypeId belongs to.
   182    * \returns this TypeId instance.
   183    *
   184    * The group name is purely an advisory information used to 
   185    * group together types according to a user-specific grouping
   186    * scheme.
   187    */
   188   TypeId SetGroupName (std::string groupName);
   189   
   190   /**
   191    * \param typeName the fully-qualified C++ typename of this TypeId.
   192    * \returns this TypeId instance.
   193    */
   194   TypeId SetTypeName (std::string typeName);
   195 
   196   /**
   197    * \returns this TypeId instance
   198    *
   199    * Record in this TypeId the fact that the default constructor
   200    * is accessible.
   201    */
   202   template <typename T>
   203   TypeId AddConstructor (void);
   204 
   205   template <typename T, typename T1>
   206   TypeId AddConstructor (void);
   207 
   208   template <typename T, typename T1, typename T2>
   209   TypeId AddConstructor (void);
   210 
   211   /**
   212    * \param name the name of the new attribute
   213    * \param help some help text which describes the purpose of this
   214    *        attribute
   215    * \param param an instance of the associated Accessor subclass
   216    * \returns this TypeId instance
   217    *
   218    * Record in this TypeId the fact that a new attribute exists.
   219    */
   220   TypeId AddAttribute (std::string name,
   221                        std::string help, 
   222                        Attribute initialValue,
   223                        Ptr<const AttributeAccessor> spec,
   224                        Ptr<const AttributeChecker> checker);
   225 
   226   /**
   227    * \param name the name of the new attribute
   228    * \param help some help text which describes the purpose of this
   229    *        attribute
   230    * \param flags flags which describe how this attribute can be read and/or written.
   231    * \param param an instance of the associated Accessor subclass
   232    * \returns this TypeId instance
   233    *
   234    * Record in this TypeId the fact that a new attribute exists.
   235    */
   236   TypeId AddAttribute (std::string name,
   237                        std::string help, 
   238                        uint32_t flags,
   239                        Attribute initialValue,
   240                        Ptr<const AttributeAccessor> accessor,
   241                        Ptr<const AttributeChecker> checker);
   242 
   243   TypeId AddTraceSource (std::string name,
   244                          std::string help,
   245                          Ptr<const TraceSourceAccessor> accessor);
   246 
   247   struct AttributeInfo {
   248     Ptr<const AttributeAccessor> accessor;
   249     Attribute initialValue;
   250     uint32_t flags;
   251     Ptr<const AttributeChecker> checker;
   252   };
   253   /**
   254    * \param name the name of the requested attribute
   255    */
   256   bool LookupAttributeByName (std::string name, struct AttributeInfo *info) const;
   257 
   258 
   259   // construct an invalid TypeId.
   260   TypeId ();
   261   ~TypeId ();
   262 
   263   VALUE_HELPER_HEADER_1 (TypeId);
   264 private:
   265   friend class Object;
   266   friend class AttributeList;
   267   friend bool operator == (TypeId a, TypeId b);
   268   friend bool operator != (TypeId a, TypeId b);
   269 
   270 
   271   Ptr<const TraceSourceAccessor> LookupTraceSourceByName (std::string name) const;
   272 
   273   /**
   274    * \param i the position of the requested attribute
   275    * \returns the Accessor associated to the requested attribute
   276    */
   277   bool LookupAttributeByPosition (uint32_t i, struct AttributeInfo *info) const;
   278   /**
   279    * \param fullName the full name of the requested attribute
   280    * \returns the Accessor associated to the requested attribute
   281    */
   282   static bool LookupAttributeByFullName (std::string fullName, struct AttributeInfo *info);
   283 
   284   explicit TypeId (uint16_t tid);
   285   void DoAddConstructor (CallbackBase callback, uint32_t nArguments);
   286   CallbackBase LookupConstructor (uint32_t nArguments) const;
   287   Ptr<const AttributeAccessor> GetAttributeAccessor (uint32_t i) const;
   288   uint32_t GetAttributeFlags (uint32_t i) const;
   289   Ptr<const AttributeChecker> GetAttributeChecker (uint32_t i) const;
   290   
   291   uint16_t m_tid;
   292 };
   293 
   294 std::ostream & operator << (std::ostream &os, TypeId tid);
   295 std::istream & operator >> (std::istream &is, TypeId &tid);
   296 
   297 VALUE_HELPER_HEADER_2 (TypeId);
   298 
   299 /**
   300  * \brief a container of attributes to be used during object's construction
   301  *        and in ns3::Object::Set.
   302  *
   303  */
   304 class AttributeList
   305 {
   306 public:
   307   AttributeList ();
   308   AttributeList (const AttributeList &o);
   309   AttributeList &operator = (const AttributeList &o);
   310   ~AttributeList ();
   311   /**
   312    * \param name the name of the attribute to set
   313    * \param value the value to set
   314    *
   315    * This method checks that a attribute with the requested
   316    * name exists and that the value specified is an acceptable
   317    * value of that attribute. If any of these checks fails,
   318    * the program terminates with a message.
   319    */
   320   bool Set (std::string name, Attribute value);
   321 
   322   bool SetWithTid (TypeId tid, std::string name, Attribute value);
   323   bool SetWithTid (TypeId tid, uint32_t position, Attribute value);
   324 
   325   /**
   326    * Clear the content of this instance.
   327    */
   328   void Reset (void);
   329 
   330   /**
   331    * \returns the global attribute container
   332    *
   333    * The global attribute container can be used to specify
   334    * a set of attribute values without having to re-specify
   335    * them for each object when it is created. This container
   336    * is checked only during object construction and 
   337    * it is always checked last, after any per-object
   338    * container is checked.
   339    */
   340   static AttributeList *GetGlobal (void);
   341 
   342   std::string SerializeToString (void) const;
   343   bool DeserializeFromString (std::string value);
   344 private:
   345   friend class Object;
   346   struct Attr {
   347     Ptr<const AttributeChecker> checker;
   348     Attribute value;
   349   };
   350   typedef std::vector<struct Attr> Attrs;
   351   typedef Attrs::iterator Iterator;
   352   typedef Attrs::const_iterator CIterator;
   353 
   354 
   355 
   356   bool DoSet (struct TypeId::AttributeInfo *info, Attribute param);
   357   void DoSetOne (Ptr<const AttributeChecker> checker, Attribute param);
   358   std::string LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const;
   359 
   360   Attrs m_attributes;
   361 };
   362 
   363 
   364 /**
   365  * \brief a base class which provides memory management and object aggregation
   366  *
   367  */
   368 class Object : public ObjectBase
   369 {
   370 public:
   371   static TypeId GetTypeId (void);
   372 
   373   Object ();
   374   virtual ~Object ();
   375 
   376   /**
   377    * \param name the name of the attribute to set
   378    * \param value the name of the attribute to set
   379    *
   380    * Set a single attribute.
   381    */
   382   bool SetAttribute (std::string name, Attribute value);
   383   /**
   384    * \param name the name of the attribute to read
   385    * \param value a reference to the string where the value of the 
   386    *        attribute should be stored.
   387    * \returns true if the requested attribute was found, false otherwise.
   388    */
   389   bool GetAttribute (std::string name, std::string &value) const;
   390   /**
   391    * \param name the name of the attribute to read
   392    * \param value a reference to the object where the value of the 
   393    *        attribute should be stored.
   394    * \returns true if the requested attribute was found, false otherwise.
   395    */
   396   Attribute GetAttribute (std::string name) const;
   397 
   398   bool TraceSourceConnect (std::string name, const CallbackBase &cb);
   399   bool TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb);
   400   bool TraceSourceDisconnect (std::string name, const CallbackBase &cb);
   401 
   402   TypeId GetRealTypeId (void) const;
   403 
   404   /**
   405    * Increment the reference count. This method should not be called
   406    * by user code. Object instances are expected to be used in conjunction
   407    * of the Ptr template which would make calling Ref unecessary and 
   408    * dangerous.
   409    */
   410   inline void Ref (void) const;
   411   /**
   412    * Decrement the reference count. This method should not be called
   413    * by user code. Object instances are expected to be used in conjunction
   414    * of the Ptr template which would make calling Ref unecessary and 
   415    * dangerous.
   416    */
   417   inline void Unref (void) const;
   418   /**
   419    * \returns a pointer to the requested interface or zero if it could not be found.
   420    */
   421   template <typename T>
   422   Ptr<T> GetObject (void) const;
   423   /**
   424    * \param tid the interface id of the requested interface
   425    * \returns a pointer to the requested interface or zero if it could not be found.
   426    */
   427   template <typename T>
   428   Ptr<T> GetObject (TypeId tid) const;
   429   /**
   430    * Run the DoDispose methods of this object and all the
   431    * objects aggregated to it.
   432    * After calling this method, the object is expected to be
   433    * totally unusable except for the Ref and Unref methods.
   434    * It is an error to call Dispose twice on the same object 
   435    * instance
   436    */
   437   void Dispose (void);
   438   /**
   439    * \param other another object pointer
   440    *
   441    * This method aggregates the two objects together: after this
   442    * method returns, it becomes possible to call GetObject
   443    * on one to get the other, and vice-versa. 
   444    */
   445   void AggregateObject (Ptr<Object> other);
   446 
   447   /**
   448    * \param path the path to match for the callback
   449    * \param cb callback to connect
   450    *
   451    * Connect the input callback to all trace sources which
   452    * match the input path.
   453    *
   454    */
   455   void TraceConnect (std::string path, const CallbackBase &cb) const;
   456   /**
   457    * \param path the path to match for the callback
   458    * \param cb callback to disconnect
   459    *
   460    * Disconnect the input callback from all trace sources which
   461    * match the input path.
   462    */
   463   void TraceDisconnect (std::string path, const CallbackBase &cb) const;
   464   /**
   465    * \returns the trace resolver associated to this object.
   466    *
   467    * This method should be rarely called by users.
   468    */
   469   virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   470 protected:
   471   /**
   472    * This method is called by Object::Dispose.
   473    * Subclasses are expected to override this method and chain
   474    * up to their parent's implementation once they are done.
   475    */
   476   virtual void DoDispose (void);
   477   virtual void NotifyConstructionCompleted (void);
   478 private:
   479   friend class TypeIdTraceResolver;
   480 
   481   template <typename T>
   482   friend Ptr<T> CreateObject (const AttributeList &attributes);
   483 
   484   template <typename T>
   485   friend Ptr<T> CreateObject (void);
   486   template <typename T, typename T1>
   487   friend Ptr<T> CreateObject (T1 a1);
   488   template <typename T, typename T1, typename T2>
   489   friend Ptr<T> CreateObject (T1 a1, T2 a2);
   490   template <typename T, typename T1, typename T2, typename T3>
   491   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3);
   492   template <typename T, typename T1, typename T2, typename T3, typename T4>
   493   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
   494   template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
   495   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   496   template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
   497   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
   498   template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   499   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
   500 
   501 
   502   bool DoSet (Ptr<const AttributeAccessor> spec, Attribute intialValue, 
   503               Ptr<const AttributeChecker> checker, Attribute value);
   504   Ptr<Object> DoGetObject (TypeId tid) const;
   505   void DoCollectSources (std::string path, const TraceContext &context, 
   506                          TraceResolver::SourceCollection *collection) const;
   507   void DoTraceAll (std::ostream &os, const TraceContext &context) const;
   508   bool Check (void) const;
   509   bool CheckLoose (void) const;
   510   /**
   511    * Attempt to delete this object. This method iterates
   512    * over all aggregated objects to check if they all 
   513    * have a zero refcount. If yes, the object and all
   514    * its aggregates are deleted. If not, nothing is done.
   515    */
   516   void MaybeDelete (void) const;
   517   /**
   518    * \param tid an TypeId
   519    *
   520    * Invoked from ns3::CreateObject only.
   521    * Initialize the m_tid member variable to
   522    * keep track of the type of this object instance.
   523    */
   524   void SetTypeId (TypeId tid);
   525   /**
   526    * \param attributes the attribute values used to initialize 
   527    *        the member variables of this object's instance.
   528    *
   529    * Invoked from ns3::CreateObject only.
   530    * Initialize all the member variables which were
   531    * registered with the associated TypeId.
   532    */
   533   void Construct (const AttributeList &attributes);
   534 
   535   /**
   536    * The reference count for this object. Each aggregate
   537    * has an individual reference count. When the global
   538    * reference count (the sum of all reference counts) 
   539    * reaches zero, the object and all its aggregates is 
   540    * deleted.
   541    */
   542   mutable uint32_t m_count;
   543   /**
   544    * Identifies the type of this object instance.
   545    */
   546   TypeId m_tid;
   547   /**
   548    * Set to true when the DoDispose method of the object
   549    * has run, false otherwise.
   550    */
   551   bool m_disposed;
   552   mutable bool m_collecting;
   553   /**
   554    * A pointer to the next aggregate object. This is a circular
   555    * linked list of aggregated objects: the last one points
   556    * back to the first one. If an object is not aggregated to
   557    * any other object, the value of this field is equal to the
   558    * value of the 'this' pointer.
   559    */
   560   Object *m_next;
   561 };
   562 
   563 } // namespace ns3
   564 
   565 namespace ns3 {
   566 
   567 /*************************************************************************
   568  *   The TypeId implementation which depends on templates
   569  *************************************************************************/
   570 
   571 template <typename T>
   572 TypeId 
   573 TypeId::SetParent (void)
   574 {
   575   return SetParent (T::GetTypeId ());
   576 }
   577 
   578 template <typename T>
   579 TypeId 
   580 TypeId::AddConstructor (void)
   581 {
   582   struct Maker {
   583     static Ptr<Object> Create (const AttributeList &attributes) {
   584       return ns3::CreateObject<T> (attributes);
   585     }
   586   };
   587   CallbackBase cb = MakeCallback (&Maker::Create);
   588   DoAddConstructor (cb, 0);
   589   return *this;
   590 }
   591 template <typename T, typename T1>
   592 TypeId 
   593 TypeId::AddConstructor (void)
   594 {
   595   struct Maker {
   596     static Ptr<Object> Create (T1 a1) {
   597       return ns3::CreateObject<T,T1> (a1);
   598     }
   599   };
   600   CallbackBase cb = MakeCallback (&Maker::Create);
   601   DoAddConstructor (cb, 1);
   602   return *this;
   603 }
   604 template <typename T, typename T1, typename T2>
   605 TypeId 
   606 TypeId::AddConstructor (void)
   607 {
   608   struct Maker {
   609     static Ptr<Object> Create (T1 a1, T2 a2) {
   610       return ns3::CreateObject<T,T1,T2> (a1, a2);
   611     }
   612   };
   613   CallbackBase cb = MakeCallback (&Maker::Create);
   614   DoAddConstructor (cb, 2);
   615   return *this;
   616 }
   617 template <typename T1>
   618 Ptr<Object> 
   619 TypeId::CreateObject (T1 a1) const
   620 {
   621   CallbackBase cb = LookupConstructor (1);
   622   Callback<Ptr<Object>,T1> realCb;
   623   realCb.Assign (cb);
   624   Ptr<Object> object = realCb (a1);
   625   return object;
   626 }
   627 template <typename T1, typename T2>
   628 Ptr<Object> 
   629 TypeId::CreateObject (T1 a1, T2 a2) const
   630 {
   631   CallbackBase cb = LookupConstructor (2);
   632   Callback<Ptr<Object>,T1,T2> realCb;
   633   realCb.Assign (cb);
   634   Ptr<Object> object = realCb (a1,a2);
   635   return object;
   636 }
   637 
   638 /*************************************************************************
   639  *   The Object implementation which depends on templates
   640  *************************************************************************/
   641 
   642 void
   643 Object::Ref (void) const
   644 {
   645   m_count++;
   646 }
   647 void
   648 Object::Unref (void) const
   649 {
   650   NS_ASSERT (Check ());
   651   m_count--;
   652   if (m_count == 0)
   653     {
   654       MaybeDelete ();
   655     }
   656 }
   657 
   658 template <typename T>
   659 Ptr<T> 
   660 Object::GetObject () const
   661 {
   662   Ptr<Object> found = DoGetObject (T::GetTypeId ());
   663   if (found != 0)
   664     {
   665       return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
   666     }
   667   return 0;
   668 }
   669 
   670 template <typename T>
   671 Ptr<T> 
   672 Object::GetObject (TypeId tid) const
   673 {
   674   Ptr<Object> found = DoGetObject (tid);
   675   if (found != 0)
   676     {
   677       return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
   678     }
   679   return 0;
   680 }
   681 
   682 /*************************************************************************
   683  *   The helper functions which need templates.
   684  *************************************************************************/
   685 
   686 
   687 template <typename T>
   688 Ptr<T> CreateObject (const AttributeList &attributes)
   689 {
   690   Ptr<T> p = Ptr<T> (new T (), false);
   691   p->SetTypeId (T::GetTypeId ());
   692   p->Object::Construct (attributes);
   693   return p;  
   694 }
   695 
   696 template <typename T>
   697 Ptr<T> CreateObject (void)
   698 {
   699   Ptr<T> p = Ptr<T> (new T (), false);
   700   p->SetTypeId (T::GetTypeId ());
   701   p->Object::Construct (AttributeList ());
   702   return p;
   703 }
   704 
   705 template <typename T, typename T1>
   706 Ptr<T> CreateObject (T1 a1)
   707 {
   708   Ptr<T> p = Ptr<T> (new T (a1), false);
   709   p->SetTypeId (T::GetTypeId ());
   710   p->Object::Construct (AttributeList ());
   711   return p;
   712 }
   713 
   714 template <typename T, typename T1, typename T2>
   715 Ptr<T> CreateObject (T1 a1, T2 a2)
   716 {
   717   Ptr<T> p = Ptr<T> (new T (a1, a2), false);
   718   p->SetTypeId (T::GetTypeId ());
   719   p->Object::Construct (AttributeList ());
   720   return p;
   721 }
   722 template <typename T, typename T1, typename T2, typename T3>
   723 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3)
   724 {
   725   Ptr<T> p = Ptr<T> (new T (a1, a2, a3), false);
   726   p->SetTypeId (T::GetTypeId ());
   727   return p;
   728 }
   729 
   730 template <typename T, typename T1, typename T2, typename T3, typename T4>
   731 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
   732 {
   733   Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4), false);
   734   p->SetTypeId (T::GetTypeId ());
   735   return p;
   736 }
   737 
   738 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
   739 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
   740 {
   741   Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5), false);
   742   p->SetTypeId (T::GetTypeId ());
   743   return p;
   744 }
   745 
   746 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
   747 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
   748 {
   749   Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5, a6), false);
   750   p->SetTypeId (T::GetTypeId ());
   751   return p;
   752 }
   753 
   754 template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   755 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
   756 {
   757   Ptr<T> p = Ptr<T> (new T (a1, a2, a3, a4, a5, a6, a7), false);
   758   p->SetTypeId (T::GetTypeId ());
   759   return p;
   760 }
   761 
   762 
   763 template <typename T>
   764 Ptr<T> 
   765 CreateObjectWith (std::string n1 = "", Attribute v1 = Attribute (),
   766                   std::string n2 = "", Attribute v2 = Attribute (),
   767                   std::string n3 = "", Attribute v3 = Attribute (),
   768                   std::string n4 = "", Attribute v4 = Attribute (),
   769                   std::string n5 = "", Attribute v5 = Attribute (),
   770                   std::string n6 = "", Attribute v6 = Attribute (),
   771                   std::string n7 = "", Attribute v7 = Attribute (),
   772                   std::string n8 = "", Attribute v8 = Attribute (),
   773                   std::string n9 = "", Attribute v9 = Attribute ())
   774               
   775 {
   776   AttributeList attributes;
   777   attributes.SetWithTid (T::GetTypeId (), n1, v1);
   778   attributes.SetWithTid (T::GetTypeId (), n2, v2);
   779   attributes.SetWithTid (T::GetTypeId (), n3, v3);
   780   attributes.SetWithTid (T::GetTypeId (), n4, v4);
   781   attributes.SetWithTid (T::GetTypeId (), n5, v5);
   782   attributes.SetWithTid (T::GetTypeId (), n6, v6);
   783   attributes.SetWithTid (T::GetTypeId (), n7, v7);
   784   attributes.SetWithTid (T::GetTypeId (), n8, v8);
   785   attributes.SetWithTid (T::GetTypeId (), n9, v9);
   786   return CreateObject<T> (attributes);
   787 }
   788 
   789 } // namespace ns3
   790 
   791 #endif /* OBJECT_H */
   792