A Discrete-Event Network Simulator
API
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  if (DoGetObject (o->GetInstanceTypeId ()))
255  {
256  NS_FATAL_ERROR ("Object::AggregateObject(): "
257  "Multiple aggregation of objects of type " <<
258  o->GetInstanceTypeId ().GetName ());
259  }
260 
261  Object *other = PeekPointer (o);
262  // first create the new aggregate buffer.
263  uint32_t total = m_aggregates->n + other->m_aggregates->n;
264  struct Aggregates *aggregates =
265  (struct Aggregates *)std::malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
266  aggregates->n = total;
267 
268  // copy our buffer to the new buffer
269  std::memcpy (&aggregates->buffer[0],
270  &m_aggregates->buffer[0],
271  m_aggregates->n*sizeof(Object*));
272 
273  // append the other buffer into the new buffer too
274  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
275  {
276  aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
277  UpdateSortedArray (aggregates, m_aggregates->n + i);
278  }
279 
280  // keep track of the old aggregate buffers for the iteration
281  // of NotifyNewAggregates
282  struct Aggregates *a = m_aggregates;
283  struct Aggregates *b = other->m_aggregates;
284 
285  // Then, assign the new aggregation buffer to every object
286  uint32_t n = aggregates->n;
287  for (uint32_t i = 0; i < n; i++)
288  {
289  Object *current = aggregates->buffer[i];
290  current->m_aggregates = aggregates;
291  }
292 
293  // Finally, call NotifyNewAggregate on all the objects aggregates together.
294  // We purposedly use the old aggregate buffers to iterate over the objects
295  // because this allows us to assume that they will not change from under
296  // our feet, even if our users call AggregateObject from within their
297  // NotifyNewAggregate method.
298  for (uint32_t i = 0; i < a->n; i++)
299  {
300  Object *current = a->buffer[i];
301  current->NotifyNewAggregate ();
302  }
303  for (uint32_t i = 0; i < b->n; i++)
304  {
305  Object *current = b->buffer[i];
306  current->NotifyNewAggregate ();
307  }
308 
309  // Now that we are done with them, we can free our old aggregate buffers
310  std::free (a);
311  std::free (b);
312 }
317 void
319 {
320  NS_LOG_FUNCTION (this);
321 }
322 
325 {
326  NS_LOG_FUNCTION (this);
327  return AggregateIterator (this);
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION (this << tid);
334  NS_ASSERT (Check ());
335  m_tid = tid;
336 }
337 
338 void
340 {
341  NS_LOG_FUNCTION (this);
343 }
344 
345 void
347 {
348  NS_LOG_FUNCTION (this);
350 }
351 
352 bool
353 Object::Check (void) const
354 {
355  NS_LOG_FUNCTION (this);
356  return (GetReferenceCount () > 0);
357 }
358 
359 /* In some cases, when an event is scheduled against a subclass of
360  * Object, and if no one owns a reference directly to this object, the
361  * object is alive, has a refcount of zero and the method ran when the
362  * event expires runs against the raw pointer which means that we are
363  * manipulating an object with a refcount of zero. So, instead we
364  * check the aggregate reference count.
365  */
366 bool
367 Object::CheckLoose (void) const
368 {
369  NS_LOG_FUNCTION (this);
370  uint32_t refcount = 0;
371  uint32_t n = m_aggregates->n;
372  for (uint32_t i = 0; i < n; i++)
373  {
374  Object *current = m_aggregates->buffer[i];
376  refcount += current->GetReferenceCount ();
377  }
378  return (refcount > 0);
379 }
380 void
382 {
383  // check if we really need to die
384  NS_LOG_FUNCTION (this);
385  for (uint32_t i = 0; i < m_aggregates->n; i++)
386  {
387  Object *current = m_aggregates->buffer[i];
388  if (current->GetReferenceCount () > 0)
389  {
390  return;
391  }
392  }
393 
394  // Now, we know that we are alone to use this aggregate so,
395  // we can dispose and delete everything safely.
396 
397  uint32_t n = m_aggregates->n;
398  // Ensure we are disposed.
399  for (uint32_t i = 0; i < n; i++)
400  {
401  Object *current = m_aggregates->buffer[i];
402  if (!current->m_disposed)
403  {
404  current->DoDispose ();
405  }
406  }
407 
408  // Now, actually delete all objects
409  struct Aggregates *aggregates = m_aggregates;
410  for (uint32_t i = 0; i < n; i++)
411  {
412  // There is a trick here: each time we call delete below,
413  // the deleted object is removed from the aggregate buffer
414  // in the destructor so, the index of the next element to
415  // lookup is always zero
416  Object *current = aggregates->buffer[0];
417  delete current;
418  }
419 }
420 } // namespace ns3
421 
void Dispose(void)
Dispose of this Object.
Definition: object.cc:208
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:346
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:847
bool Check(void) const
Verify that this Object is still live, by checking it's reference count.
Definition: object.cc:353
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:145
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
Anchor the ns-3 type and attribute system.
Definition: object-base.h:68
STL namespace.
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:324
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:381
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
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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
std::string GetName(void) const
Get the name.
Definition: type-id.cc:880
void SetTypeId(TypeId tid)
Set the TypeId of this Object.
Definition: object.cc:331
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:367
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:318
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:826
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