A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
object.cc
Go to the documentation of this file.
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 
22 #include "object.h"
23 #include "object-factory.h"
24 #include "assert.h"
25 #include "attribute.h"
26 #include "log.h"
27 #include "string.h"
28 #include <vector>
29 #include <sstream>
30 #include <cstdlib>
31 #include <cstring>
32 
39 namespace ns3 {
40 
41 NS_LOG_COMPONENT_DEFINE ("Object");
42 
43 /*********************************************************************
44  * The Object implementation
45  *********************************************************************/
46 
48 
50  : m_object (0),
51  m_current (0)
52 {
53  NS_LOG_FUNCTION (this);
54 }
55 
56 bool
58 {
59  NS_LOG_FUNCTION (this);
60  return m_current < m_object->m_aggregates->n;
61 }
64 {
65  NS_LOG_FUNCTION (this);
66  Object *object = m_object->m_aggregates->buffer[m_current];
67  m_current++;
68  return object;
69 }
71  : m_object (object),
72  m_current (0)
73 {
74  NS_LOG_FUNCTION (this << object);
75 }
76 
77 
78 TypeId
80 {
81  NS_LOG_FUNCTION (this);
82  return m_tid;
83 }
84 
85 TypeId
87 {
88  static TypeId tid = TypeId ("ns3::Object")
90  .SetGroupName ("Core")
91  ;
92  return tid;
93 }
94 
95 
97  : m_tid (Object::GetTypeId ()),
98  m_disposed (false),
99  m_initialized (false),
100  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
101  m_getObjectCount (0)
102 {
103  NS_LOG_FUNCTION (this);
104  m_aggregates->n = 1;
105  m_aggregates->buffer[0] = this;
106 }
108 {
109  // remove this object from the aggregate list
110  NS_LOG_FUNCTION (this);
111  uint32_t n = m_aggregates->n;
112  for (uint32_t i = 0; i < n; i++)
113  {
114  Object *current = m_aggregates->buffer[i];
115  if (current == this)
116  {
117  std::memmove (&m_aggregates->buffer[i],
118  &m_aggregates->buffer[i+1],
119  sizeof (Object *)*(m_aggregates->n - (i+1)));
120  m_aggregates->n--;
121  }
122  }
123  // finally, if all objects have been removed from the list,
124  // delete the aggregate list
125  if (m_aggregates->n == 0)
126  {
127  std::free (m_aggregates);
128  }
129  m_aggregates = 0;
130 }
132  : m_tid (o.m_tid),
133  m_disposed (false),
134  m_initialized (false),
135  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
136  m_getObjectCount (0)
137 {
138  m_aggregates->n = 1;
139  m_aggregates->buffer[0] = this;
140 }
141 void
143 {
144  NS_LOG_FUNCTION (this << &attributes);
145  ConstructSelf (attributes);
146 }
147 
150 {
151  NS_LOG_FUNCTION (this << tid);
152  NS_ASSERT (CheckLoose ());
153 
154  uint32_t n = m_aggregates->n;
155  TypeId objectTid = Object::GetTypeId ();
156  for (uint32_t i = 0; i < n; i++)
157  {
158  Object *current = m_aggregates->buffer[i];
159  TypeId cur = current->GetInstanceTypeId ();
160  while (cur != tid && cur != objectTid)
161  {
162  cur = cur.GetParent ();
163  }
164  if (cur == tid)
165  {
166  // This is an attempt to 'cache' the result of this lookup.
167  // the idea is that if we perform a lookup for a TypeId on this object,
168  // we are likely to perform the same lookup later so, we make sure
169  // that the aggregate array is sorted by the number of accesses
170  // to each object.
171 
172  // first, increment the access count
173  current->m_getObjectCount++;
174  // then, update the sort
176  // finally, return the match
177  return const_cast<Object *> (current);
178  }
179  }
180  return 0;
181 }
182 void
184 {
193  NS_LOG_FUNCTION (this);
194 restart:
195  uint32_t n = m_aggregates->n;
196  for (uint32_t i = 0; i < n; i++)
197  {
198  Object *current = m_aggregates->buffer[i];
199  if (!current->m_initialized)
200  {
201  current->DoInitialize ();
202  current->m_initialized = true;
203  goto restart;
204  }
205  }
206 }
207 void
209 {
218  NS_LOG_FUNCTION (this);
219 restart:
220  uint32_t n = m_aggregates->n;
221  for (uint32_t i = 0; i < n; i++)
222  {
223  Object *current = m_aggregates->buffer[i];
224  if (!current->m_disposed)
225  {
226  current->DoDispose ();
227  current->m_disposed = true;
228  goto restart;
229  }
230  }
231 }
232 void
233 Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
234 {
235  NS_LOG_FUNCTION (this << aggregates << j);
236  while (j > 0 &&
237  aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
238  {
239  Object *tmp = aggregates->buffer[j-1];
240  aggregates->buffer[j-1] = aggregates->buffer[j];
241  aggregates->buffer[j] = tmp;
242  j--;
243  }
244 }
245 void
247 {
248  NS_LOG_FUNCTION (this << o);
250  NS_ASSERT (!o->m_disposed);
251  NS_ASSERT (CheckLoose ());
252  NS_ASSERT (o->CheckLoose ());
253 
254  Object *other = PeekPointer (o);
255  // first create the new aggregate buffer.
256  uint32_t total = m_aggregates->n + other->m_aggregates->n;
257  struct Aggregates *aggregates =
258  (struct Aggregates *)std::malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
259  aggregates->n = total;
260 
261  // copy our buffer to the new buffer
262  std::memcpy (&aggregates->buffer[0],
263  &m_aggregates->buffer[0],
264  m_aggregates->n*sizeof(Object*));
265 
266  // append the other buffer into the new buffer too
267  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
268  {
269  aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
270  const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId ();
271  if (DoGetObject (typeId))
272  {
273  NS_FATAL_ERROR ("Object::AggregateObject(): "
274  "Multiple aggregation of objects of type " <<
275  other->GetInstanceTypeId () <<
276  " on objects of type " << typeId);
277  }
278  UpdateSortedArray (aggregates, m_aggregates->n + i);
279  }
280 
281  // keep track of the old aggregate buffers for the iteration
282  // of NotifyNewAggregates
283  struct Aggregates *a = m_aggregates;
284  struct Aggregates *b = other->m_aggregates;
285 
286  // Then, assign the new aggregation buffer to every object
287  uint32_t n = aggregates->n;
288  for (uint32_t i = 0; i < n; i++)
289  {
290  Object *current = aggregates->buffer[i];
291  current->m_aggregates = aggregates;
292  }
293 
294  // Finally, call NotifyNewAggregate on all the objects aggregates together.
295  // We purposedly use the old aggregate buffers to iterate over the objects
296  // because this allows us to assume that they will not change from under
297  // our feet, even if our users call AggregateObject from within their
298  // NotifyNewAggregate method.
299  for (uint32_t i = 0; i < a->n; i++)
300  {
301  Object *current = a->buffer[i];
302  current->NotifyNewAggregate ();
303  }
304  for (uint32_t i = 0; i < b->n; i++)
305  {
306  Object *current = b->buffer[i];
307  current->NotifyNewAggregate ();
308  }
309 
310  // Now that we are done with them, we can free our old aggregate buffers
311  std::free (a);
312  std::free (b);
313 }
318 void
320 {
321  NS_LOG_FUNCTION (this);
322 }
323 
326 {
327  NS_LOG_FUNCTION (this);
328  return AggregateIterator (this);
329 }
330 
331 void
333 {
334  NS_LOG_FUNCTION (this << tid);
335  NS_ASSERT (Check ());
336  m_tid = tid;
337 }
338 
339 void
341 {
342  NS_LOG_FUNCTION (this);
344 }
345 
346 void
348 {
349  NS_LOG_FUNCTION (this);
351 }
352 
353 bool
354 Object::Check (void) const
355 {
356  NS_LOG_FUNCTION (this);
357  return (GetReferenceCount () > 0);
358 }
359 
360 /* In some cases, when an event is scheduled against a subclass of
361  * Object, and if no one owns a reference directly to this object, the
362  * object is alive, has a refcount of zero and the method ran when the
363  * event expires runs against the raw pointer which means that we are
364  * manipulating an object with a refcount of zero. So, instead we
365  * check the aggregate reference count.
366  */
367 bool
368 Object::CheckLoose (void) const
369 {
370  NS_LOG_FUNCTION (this);
371  uint32_t refcount = 0;
372  uint32_t n = m_aggregates->n;
373  for (uint32_t i = 0; i < n; i++)
374  {
375  Object *current = m_aggregates->buffer[i];
377  refcount += current->GetReferenceCount ();
378  }
379  return (refcount > 0);
380 }
381 void
383 {
384  // check if we really need to die
385  NS_LOG_FUNCTION (this);
386  for (uint32_t i = 0; i < m_aggregates->n; i++)
387  {
388  Object *current = m_aggregates->buffer[i];
389  if (current->GetReferenceCount () > 0)
390  {
391  return;
392  }
393  }
394 
395  // Now, we know that we are alone to use this aggregate so,
396  // we can dispose and delete everything safely.
397 
398  uint32_t n = m_aggregates->n;
399  // Ensure we are disposed.
400  for (uint32_t i = 0; i < n; i++)
401  {
402  Object *current = m_aggregates->buffer[i];
403  if (!current->m_disposed)
404  {
405  current->DoDispose ();
406  }
407  }
408 
409  // Now, actually delete all objects
410  struct Aggregates *aggregates = m_aggregates;
411  for (uint32_t i = 0; i < n; i++)
412  {
413  // There is a trick here: each time we call delete below,
414  // the deleted object is removed from the aggregate buffer
415  // in the destructor so, the index of the next element to
416  // lookup is always zero
417  Object *current = aggregates->buffer[0];
418  delete current;
419  }
420 }
421 } // namespace ns3
422 
void Dispose(void)
Dispose of this Object.
Definition: object.cc:208
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:347
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void Construct(const AttributeConstructionList &attributes)
Initialize all member variables registered as Attributes of this TypeId.
Definition: object.cc:142
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
String attribute value declarations.
bool m_disposed
Set to true when the DoDispose() method of the Object has run, false otherwise.
Definition: object.h:409
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:246
ns3::ObjectFactory class declaration.
uint32_t m_getObjectCount
The number of times the Object was accessed with a call to GetObject().
Definition: object.h:430
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:562
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
TypeId GetParent(void) const
Get the parent of this TypeId.
Definition: type-id.cc:848
bool Check(void) const
Verify that this Object is still live, by checking it's reference count.
Definition: object.cc:354
struct Aggregates * m_aggregates
A pointer to an array of 'aggregates'.
Definition: object.h:422
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:340
Anchor the ns-3 type and attribute system.
Definition: object-base.h:68
bool m_initialized
Set to true once the DoInitialize() method has run, false otherwise.
Definition: object.h:414
Object * buffer[1]
The array of Objects.
Definition: object.h:335
AggregateIterator GetAggregateIterator(void) const
Get an iterator to the Objects aggregated to this one.
Definition: object.cc:325
uint32_t GetReferenceCount(void) const
Get the reference count of the object.
Ptr< const Object > Next(void)
Get the next Aggregated Object.
Definition: object.cc:63
AggregateIterator()
Default constructor, which has no Object.
Definition: object.cc:49
void DoDelete(void)
Attempt to delete this Object.
Definition: object.cc:382
Definition of assertion macros NS_ASSERT() and NS_ASSERT_MSG().
ns3::AttributeValue, ns3::AttributeAccessor and ns3::AttributeChecker declarations.
List of Attribute name, value and checker triples used to construct Objects.
uint32_t n
The number of entries in buffer.
Definition: object.h:333
Ptr< Object > DoGetObject(TypeId tid) const
Find an Object of TypeId tid in the aggregates of this Object.
Definition: object.cc:149
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
Definition: object-base.cc:80
virtual TypeId GetInstanceTypeId(void) const
Implement the GetInstanceTypeId method defined in ObjectBase.
Definition: object.cc:79
TypeId m_tid
Identifies the type of this Object instance.
Definition: object.h:404
void SetTypeId(TypeId tid)
Set the TypeId of this Object.
Definition: object.cc:332
static TypeId GetTypeId(void)
Register this type.
Definition: object.cc:86
friend class AggregateIterator
Definition: object.h:316
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
bool HasNext(void) const
Check if there are more Aggregates to iterate over.
Definition: object.cc:57
bool CheckLoose(void) const
Check if any aggregated Objects have non-zero reference counts.
Definition: object.cc:368
virtual ~Object()
Destructor.
Definition: object.cc:107
void UpdateSortedArray(struct Aggregates *aggregates, uint32_t i) const
Keep the list of aggregates in most-recently-used order.
Definition: object.cc:233
A base class which provides memory management and object aggregation.
Definition: object.h:87
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:319
Debug message logging.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:827
Iterate over the Objects aggregated to an ns3::Object.
Definition: object.h:104
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
The list of Objects aggregated to this one.
Definition: object.h:331
Object()
Constructor.
Definition: object.cc:96