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 bool
209 {
210  NS_LOG_FUNCTION (this);
211  return m_initialized;
212 }
213 void
215 {
224  NS_LOG_FUNCTION (this);
225 restart:
226  uint32_t n = m_aggregates->n;
227  for (uint32_t i = 0; i < n; i++)
228  {
229  Object *current = m_aggregates->buffer[i];
230  if (!current->m_disposed)
231  {
232  current->DoDispose ();
233  current->m_disposed = true;
234  goto restart;
235  }
236  }
237 }
238 void
239 Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
240 {
241  NS_LOG_FUNCTION (this << aggregates << j);
242  while (j > 0
243  && aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j - 1]->m_getObjectCount)
244  {
245  Object *tmp = aggregates->buffer[j - 1];
246  aggregates->buffer[j - 1] = aggregates->buffer[j];
247  aggregates->buffer[j] = tmp;
248  j--;
249  }
250 }
251 void
253 {
254  NS_LOG_FUNCTION (this << o);
256  NS_ASSERT (!o->m_disposed);
257  NS_ASSERT (CheckLoose ());
258  NS_ASSERT (o->CheckLoose ());
259 
260  Object *other = PeekPointer (o);
261  // first create the new aggregate buffer.
262  uint32_t total = m_aggregates->n + other->m_aggregates->n;
263  struct Aggregates *aggregates =
264  (struct Aggregates *)std::malloc (sizeof(struct Aggregates) + (total - 1) * sizeof(Object*));
265  aggregates->n = total;
266 
267  // copy our buffer to the new buffer
268  std::memcpy (&aggregates->buffer[0],
269  &m_aggregates->buffer[0],
270  m_aggregates->n * sizeof(Object*));
271 
272  // append the other buffer into the new buffer too
273  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
274  {
275  aggregates->buffer[m_aggregates->n + i] = other->m_aggregates->buffer[i];
276  const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId ();
277  if (DoGetObject (typeId))
278  {
279  NS_FATAL_ERROR ("Object::AggregateObject(): "
280  "Multiple aggregation of objects of type " <<
281  other->GetInstanceTypeId () <<
282  " on objects of type " << typeId);
283  }
284  UpdateSortedArray (aggregates, m_aggregates->n + i);
285  }
286 
287  // keep track of the old aggregate buffers for the iteration
288  // of NotifyNewAggregates
289  struct Aggregates *a = m_aggregates;
290  struct Aggregates *b = other->m_aggregates;
291 
292  // Then, assign the new aggregation buffer to every object
293  uint32_t n = aggregates->n;
294  for (uint32_t i = 0; i < n; i++)
295  {
296  Object *current = aggregates->buffer[i];
297  current->m_aggregates = aggregates;
298  }
299 
300  // Finally, call NotifyNewAggregate on all the objects aggregates together.
301  // We purposely use the old aggregate buffers to iterate over the objects
302  // because this allows us to assume that they will not change from under
303  // our feet, even if our users call AggregateObject from within their
304  // NotifyNewAggregate method.
305  for (uint32_t i = 0; i < a->n; i++)
306  {
307  Object *current = a->buffer[i];
308  current->NotifyNewAggregate ();
309  }
310  for (uint32_t i = 0; i < b->n; i++)
311  {
312  Object *current = b->buffer[i];
313  current->NotifyNewAggregate ();
314  }
315 
316  // Now that we are done with them, we can free our old aggregate buffers
317  std::free (a);
318  std::free (b);
319 }
324 void
326 {
327  NS_LOG_FUNCTION (this);
328 }
329 
332 {
333  NS_LOG_FUNCTION (this);
334  return AggregateIterator (this);
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION (this << tid);
341  NS_ASSERT (Check ());
342  m_tid = tid;
343 }
344 
345 void
347 {
348  NS_LOG_FUNCTION (this);
350 }
351 
352 void
354 {
355  NS_LOG_FUNCTION (this);
357 }
358 
359 bool
360 Object::Check (void) const
361 {
362  NS_LOG_FUNCTION (this);
363  return (GetReferenceCount () > 0);
364 }
365 
366 /* In some cases, when an event is scheduled against a subclass of
367  * Object, and if no one owns a reference directly to this object, the
368  * object is alive, has a refcount of zero and the method ran when the
369  * event expires runs against the raw pointer which means that we are
370  * manipulating an object with a refcount of zero. So, instead we
371  * check the aggregate reference count.
372  */
373 bool
374 Object::CheckLoose (void) const
375 {
376  NS_LOG_FUNCTION (this);
377  bool nonZeroRefCount = false;
378  uint32_t n = m_aggregates->n;
379  for (uint32_t i = 0; i < n; i++)
380  {
381  Object *current = m_aggregates->buffer[i];
382  if (current->GetReferenceCount ())
383  {
384  nonZeroRefCount = true;
385  break;
386  }
387  }
388  return nonZeroRefCount;
389 }
390 void
392 {
393  // check if we really need to die
394  NS_LOG_FUNCTION (this);
395  for (uint32_t i = 0; i < m_aggregates->n; i++)
396  {
397  Object *current = m_aggregates->buffer[i];
398  if (current->GetReferenceCount () > 0)
399  {
400  return;
401  }
402  }
403 
404  // Now, we know that we are alone to use this aggregate so,
405  // we can dispose and delete everything safely.
406 
407  uint32_t n = m_aggregates->n;
408  // Ensure we are disposed.
409  for (uint32_t i = 0; i < n; i++)
410  {
411  Object *current = m_aggregates->buffer[i];
412  if (!current->m_disposed)
413  {
414  current->DoDispose ();
415  }
416  }
417 
418  // Now, actually delete all objects
419  struct Aggregates *aggregates = m_aggregates;
420  for (uint32_t i = 0; i < n; i++)
421  {
422  // There is a trick here: each time we call delete below,
423  // the deleted object is removed from the aggregate buffer
424  // in the destructor so, the index of the next element to
425  // lookup is always zero
426  Object *current = aggregates->buffer[0];
427  delete current;
428  }
429 }
430 } // namespace ns3
431 
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
ns3::AttributeValue, ns3::AttributeAccessor and ns3::AttributeChecker declarations.
List of Attribute name, value and checker triples used to construct Objects.
Iterate over the Objects aggregated to an ns3::Object.
Definition: object.h:105
AggregateIterator()
Default constructor, which has no Object.
Definition: object.cc:49
Ptr< const Object > Next(void)
Get the next Aggregated Object.
Definition: object.cc:63
bool HasNext(void) const
Check if there are more Aggregates to iterate over.
Definition: object.cc:57
Anchor the ns-3 type and attribute system.
Definition: object-base.h:120
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
Definition: object-base.cc:159
A base class which provides memory management and object aggregation.
Definition: object.h:88
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
Definition: object.cc:79
struct Aggregates * m_aggregates
A pointer to an array of 'aggregates'.
Definition: object.h:437
bool IsInitialized(void) const
Check if the object has been initialized.
Definition: object.cc:208
AggregateIterator GetAggregateIterator(void) const
Get an iterator to the Objects aggregated to this one.
Definition: object.cc:331
void Construct(const AttributeConstructionList &attributes)
Initialize all member variables registered as Attributes of this TypeId.
Definition: object.cc:142
Ptr< Object > DoGetObject(TypeId tid) const
Find an Object of TypeId tid in the aggregates of this Object.
Definition: object.cc:149
friend class AggregateIterator
Friends.
Definition: object.h:329
bool m_disposed
Set to true when the DoDispose() method of the Object has run, false otherwise.
Definition: object.h:424
bool CheckLoose(void) const
Check if any aggregated Objects have non-zero reference counts.
Definition: object.cc:374
static TypeId GetTypeId(void)
Register this type.
Definition: object.cc:86
void UpdateSortedArray(struct Aggregates *aggregates, uint32_t i) const
Keep the list of aggregates in most-recently-used order.
Definition: object.cc:239
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
bool Check(void) const
Verify that this Object is still live, by checking it's reference count.
Definition: object.cc:360
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:353
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:183
virtual ~Object()
Destructor.
Definition: object.cc:107
void SetTypeId(TypeId tid)
Set the TypeId of this Object.
Definition: object.cc:338
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
TypeId m_tid
Identifies the type of this Object instance.
Definition: object.h:419
Object()
Constructor.
Definition: object.cc:96
void DoDelete(void)
Attempt to delete this Object.
Definition: object.cc:391
uint32_t m_getObjectCount
The number of times the Object was accessed with a call to GetObject().
Definition: object.h:445
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
bool m_initialized
Set to true once the DoInitialize() method has run, false otherwise.
Definition: object.h:429
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
uint32_t GetReferenceCount(void) const
Get the reference count of the object.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId GetParent(void) const
Get the parent of this TypeId.
Definition: type-id.cc:943
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#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
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Debug message logging.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
ns3::ObjectFactory class declaration.
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
ns3::StringValue attribute value declarations.
The list of Objects aggregated to this one.
Definition: object.h:346
uint32_t n
The number of entries in buffer.
Definition: object.h:348
Object * buffer[1]
The array of Objects.
Definition: object.h:350