src/core/object.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3871 c6f693de286d
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 #include "object.h"
    22 #include "assert.h"
    23 #include "singleton.h"
    24 #include "attribute.h"
    25 #include "log.h"
    26 #include "string.h"
    27 #include <vector>
    28 #include <sstream>
    29 
    30 NS_LOG_COMPONENT_DEFINE ("Object");
    31 
    32 namespace ns3 {
    33 
    34 /*********************************************************************
    35  *         The Object implementation
    36  *********************************************************************/
    37 
    38 NS_OBJECT_ENSURE_REGISTERED (Object);
    39 
    40 Object::AggregateIterator::AggregateIterator ()
    41   : m_first (0),
    42     m_current (0)
    43 {}
    44 
    45 bool 
    46 Object::AggregateIterator::HasNext (void) const
    47 {
    48   if (m_current != 0 && m_current->m_next != PeekPointer (m_first))
    49     {
    50       return true;
    51     }
    52   return false;
    53 }
    54 Ptr<const Object> 
    55 Object::AggregateIterator::Next (void)
    56 {
    57   m_current = m_current->m_next;
    58   return m_current;
    59 }
    60 Object::AggregateIterator::AggregateIterator (Ptr<const Object> first)
    61   : m_first (first),
    62     m_current (first)
    63 {}
    64 
    65 
    66 TypeId 
    67 Object::GetInstanceTypeId (void) const
    68 {
    69   return m_tid;
    70 }
    71 
    72 TypeId 
    73 Object::GetTypeId (void)
    74 {
    75   static TypeId tid = TypeId ("ns3::Object")
    76     .SetParent<ObjectBase> ()
    77     ;
    78   return tid;
    79 }
    80 
    81 
    82 Object::Object ()
    83   : m_count (1),
    84     m_tid (Object::GetTypeId ()),
    85     m_disposed (false),
    86     m_next (this)
    87 {}
    88 Object::~Object () 
    89 {
    90   m_next = 0;
    91 }
    92 Object::Object (const Object &o)
    93   : m_count (1),
    94     m_tid (o.m_tid),
    95     m_disposed (false),
    96     m_next (this)
    97 {}
    98 uint32_t
    99 Object::GetReferenceCount (void) const
   100 {
   101   return m_count;
   102 }
   103 void
   104 Object::Construct (const AttributeList &attributes)
   105 {
   106   ConstructSelf (attributes);
   107 }
   108 
   109 Ptr<Object>
   110 Object::DoGetObject (TypeId tid) const
   111 {
   112   NS_ASSERT (CheckLoose ());
   113   const Object *currentObject = this;
   114   TypeId objectTid = Object::GetTypeId ();
   115   do {
   116     NS_ASSERT (currentObject != 0);
   117     TypeId cur = currentObject->GetInstanceTypeId ();
   118     while (cur != tid && cur != objectTid)
   119       {
   120         cur = cur.GetParent ();
   121       }
   122     if (cur == tid)
   123       {
   124         return const_cast<Object *> (currentObject);
   125       }
   126     currentObject = currentObject->m_next;
   127   } while (currentObject != this);
   128   return 0;
   129 }
   130 void 
   131 Object::Dispose (void)
   132 {
   133   Object *current = this;
   134   do {
   135     NS_ASSERT (current != 0);
   136     NS_ASSERT (!current->m_disposed);
   137     current->DoDispose ();
   138     current->m_disposed = true;
   139     current = current->m_next;
   140   } while (current != this);
   141 }
   142 void 
   143 Object::AggregateObject (Ptr<Object> o)
   144 {
   145   NS_ASSERT (!m_disposed);
   146   NS_ASSERT (!o->m_disposed);
   147   NS_ASSERT (CheckLoose ());
   148   NS_ASSERT (o->CheckLoose ());
   149 
   150   if (DoGetObject (o->GetInstanceTypeId ()))
   151     {
   152       NS_FATAL_ERROR ("Object::AggregateObject(): "
   153                       "Multiple aggregation of objects of type " << 
   154                       o->GetInstanceTypeId ().GetName ());
   155     }
   156 
   157   Object *other = PeekPointer (o);
   158   Object *next = m_next;
   159   m_next = other->m_next;
   160   other->m_next = next;
   161   NS_ASSERT (CheckLoose ());
   162   NS_ASSERT (o->CheckLoose ());
   163   // call NotifyNewAggregate in the listed chain
   164   Object *currentObject = this;
   165   do 
   166     {
   167       // the NotifyNewAggregate of the current object implementation
   168       // should be called on the next object in the linked chain
   169       currentObject->NotifyNewAggregate ();
   170       currentObject = currentObject->m_next;
   171     } while (currentObject != this);
   172 }
   173 /**
   174  * This function must be implemented in the stack that needs to notify
   175  * other stacks connected to the node of their presence in the node.
   176  */
   177 void
   178 Object::NotifyNewAggregate ()
   179 {
   180 
   181 }
   182 
   183 Object::AggregateIterator 
   184 Object::GetAggregateIterator (void) const
   185 {
   186   return AggregateIterator (this);
   187 }
   188 
   189 void 
   190 Object::SetTypeId (TypeId tid)
   191 {
   192   NS_ASSERT (Check ());
   193   m_tid = tid;
   194 }
   195 
   196 void
   197 Object::DoDispose (void)
   198 {
   199   NS_ASSERT (!m_disposed);
   200 }
   201 
   202 
   203 bool 
   204 Object::Check (void) const
   205 {
   206   return (m_count > 0);
   207 }
   208 
   209 /* In some cases, when an event is scheduled against a subclass of
   210  * Object, and if no one owns a reference directly to this object, the
   211  * object is alive, has a refcount of zero and the method ran when the
   212  * event expires runs against the raw pointer which means that we are
   213  * manipulating an object with a refcount of zero.  So, instead we
   214  * check the aggregate reference count.
   215  */
   216 bool 
   217 Object::CheckLoose (void) const
   218 {
   219   uint32_t refcount = 0;
   220   const Object *current = this;
   221   do
   222     {
   223       refcount += current->m_count;
   224       current = current->m_next;
   225     }
   226   while (current != this);
   227 
   228   return (refcount > 0);
   229 }
   230 
   231 void
   232 Object::MaybeDelete (void) const
   233 {
   234   // First, check if any of the attached
   235   // Object has a non-zero count.
   236   const Object *current = this;
   237   do {
   238     NS_ASSERT (current != 0);
   239     if (current->m_count != 0)
   240       {
   241         return;
   242       }
   243     current = current->m_next;
   244   } while (current != this);
   245 
   246   // Ensure we are disposed.
   247   Object *tmp = const_cast<Object *> (this);
   248   const Object *end = this;
   249   do {
   250     NS_ASSERT (current != 0);
   251     Object *next = tmp->m_next;
   252     if (!tmp->m_disposed)
   253       {
   254         tmp->DoDispose ();
   255       }
   256     tmp = next;
   257   } while (tmp != end);
   258 
   259   // all attached objects have a zero count so, 
   260   // we can delete all attached objects.
   261   current = this;
   262   do {
   263     NS_ASSERT (current != 0);
   264     Object *next = current->m_next;
   265     delete current;
   266     current = next;
   267   } while (current != end);
   268 }
   269 
   270 } // namespace ns3
   271 
   272 
   273 #ifdef RUN_SELF_TESTS
   274 
   275 #include "test.h"
   276 #include "object-factory.h"
   277 
   278 namespace {
   279 
   280 class BaseA : public ns3::Object
   281 {
   282 public:
   283   static ns3::TypeId GetTypeId (void) {
   284     static ns3::TypeId tid = ns3::TypeId ("BaseA")
   285       .SetParent (Object::GetTypeId ())
   286       .HideFromDocumentation ()
   287       .AddConstructor<BaseA> ();
   288     return tid;
   289   }
   290   BaseA ()
   291   {}
   292   virtual void Dispose (void) {}
   293 };
   294 
   295 class DerivedA : public BaseA
   296 {
   297 public:
   298   static ns3::TypeId GetTypeId (void) {
   299     static ns3::TypeId tid = ns3::TypeId ("DerivedA")
   300       .SetParent (BaseA::GetTypeId ())
   301       .HideFromDocumentation ()
   302       .AddConstructor<DerivedA> ();
   303     return tid;
   304   }
   305   DerivedA ()
   306   {}
   307   virtual void Dispose (void) {
   308     BaseA::Dispose ();
   309   }
   310 };
   311 
   312 class BaseB : public ns3::Object
   313 {
   314 public:
   315   static ns3::TypeId GetTypeId (void) {
   316     static ns3::TypeId tid = ns3::TypeId ("BaseB")
   317       .SetParent (Object::GetTypeId ())
   318       .HideFromDocumentation ()
   319       .AddConstructor<BaseB> ();
   320     return tid;
   321   }
   322   BaseB ()
   323   {}
   324   virtual void Dispose (void) {}
   325 };
   326 
   327 class DerivedB : public BaseB
   328 {
   329 public:
   330   static ns3::TypeId GetTypeId (void) {
   331     static ns3::TypeId tid = ns3::TypeId ("DerivedB")
   332       .SetParent (BaseB::GetTypeId ())
   333       .HideFromDocumentation ()
   334       .AddConstructor<DerivedB> ();
   335     return tid;
   336   }
   337   DerivedB ()
   338   {}
   339   virtual void Dispose (void) {
   340     BaseB::Dispose ();
   341   }
   342 };
   343 
   344 NS_OBJECT_ENSURE_REGISTERED (BaseA);
   345 NS_OBJECT_ENSURE_REGISTERED (DerivedA);
   346 NS_OBJECT_ENSURE_REGISTERED (BaseB);
   347 NS_OBJECT_ENSURE_REGISTERED (DerivedB);
   348 
   349 } // namespace anonymous
   350 
   351 namespace ns3 {
   352 
   353 class ObjectTest : public Test
   354 {
   355 public:
   356   ObjectTest ();
   357   virtual bool RunTests (void);
   358 };
   359 
   360 ObjectTest::ObjectTest ()
   361   : Test ("Object")
   362 {}
   363 
   364 bool 
   365 ObjectTest::RunTests (void)
   366 {
   367   bool result = true;
   368 
   369   Ptr<BaseA> baseA = CreateObject<BaseA> ();
   370   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
   371   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
   372   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
   373   baseA = CreateObject<DerivedA> ();
   374   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
   375   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
   376   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
   377 
   378   baseA = CreateObject<BaseA> ();
   379   Ptr<BaseB> baseB = CreateObject<BaseB> ();
   380   Ptr<BaseB> baseBCopy = baseB;
   381   baseA->AggregateObject (baseB);
   382   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseA> (), 0);
   383   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
   384   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
   385   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedB> (), 0);
   386   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
   387   NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedB> (), 0);
   388   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
   389   NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
   390   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
   391 
   392   baseA = CreateObject<DerivedA> ();
   393   baseB = CreateObject<DerivedB> ();
   394   baseBCopy = baseB;
   395   baseA->AggregateObject (baseB);
   396   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
   397   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
   398   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedA> (), 0);
   399   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
   400   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
   401   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
   402   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
   403   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
   404 
   405   baseA = CreateObject<BaseA> ();
   406   baseB = CreateObject<BaseB> ();
   407   baseA->AggregateObject (baseB);
   408   baseA = 0;
   409   baseA = baseB->GetObject<BaseA> ();
   410 
   411 
   412   // Test the object creation code of TypeId
   413   ObjectFactory factory;
   414   factory.SetTypeId (BaseA::GetTypeId ());
   415   Ptr<Object> a = factory.Create ();
   416   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
   417   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
   418   NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
   419   factory.SetTypeId (DerivedA::GetTypeId ());
   420   a = factory.Create ();
   421   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
   422   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
   423   NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
   424 
   425 
   426   return result;
   427 }
   428 
   429 static ObjectTest g_interfaceObjectTests;
   430 
   431 
   432 } // namespace ns3
   433 
   434 #endif /* RUN_SELF_TESTS */
   435 
   436