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  ;
91  return tid;
92 }
93 
94 
96  : m_tid (Object::GetTypeId ()),
97  m_disposed (false),
98  m_initialized (false),
99  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
100  m_getObjectCount (0)
101 {
102  NS_LOG_FUNCTION (this);
103  m_aggregates->n = 1;
104  m_aggregates->buffer[0] = this;
105 }
107 {
108  // remove this object from the aggregate list
109  NS_LOG_FUNCTION (this);
110  uint32_t n = m_aggregates->n;
111  for (uint32_t i = 0; i < n; i++)
112  {
113  Object *current = m_aggregates->buffer[i];
114  if (current == this)
115  {
116  std::memmove (&m_aggregates->buffer[i],
117  &m_aggregates->buffer[i+1],
118  sizeof (Object *)*(m_aggregates->n - (i+1)));
119  m_aggregates->n--;
120  }
121  }
122  // finally, if all objects have been removed from the list,
123  // delete the aggregate list
124  if (m_aggregates->n == 0)
125  {
126  std::free (m_aggregates);
127  }
128  m_aggregates = 0;
129 }
131  : m_tid (o.m_tid),
132  m_disposed (false),
133  m_initialized (false),
134  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
135  m_getObjectCount (0)
136 {
137  m_aggregates->n = 1;
138  m_aggregates->buffer[0] = this;
139 }
140 void
142 {
143  NS_LOG_FUNCTION (this << &attributes);
144  ConstructSelf (attributes);
145 }
146 
149 {
150  NS_LOG_FUNCTION (this << tid);
151  NS_ASSERT (CheckLoose ());
152 
153  uint32_t n = m_aggregates->n;
154  TypeId objectTid = Object::GetTypeId ();
155  for (uint32_t i = 0; i < n; i++)
156  {
157  Object *current = m_aggregates->buffer[i];
158  TypeId cur = current->GetInstanceTypeId ();
159  while (cur != tid && cur != objectTid)
160  {
161  cur = cur.GetParent ();
162  }
163  if (cur == tid)
164  {
165  // This is an attempt to 'cache' the result of this lookup.
166  // the idea is that if we perform a lookup for a TypeId on this object,
167  // we are likely to perform the same lookup later so, we make sure
168  // that the aggregate array is sorted by the number of accesses
169  // to each object.
170 
171  // first, increment the access count
172  current->m_getObjectCount++;
173  // then, update the sort
175  // finally, return the match
176  return const_cast<Object *> (current);
177  }
178  }
179  return 0;
180 }
181 void
183 {
192  NS_LOG_FUNCTION (this);
193 restart:
194  uint32_t n = m_aggregates->n;
195  for (uint32_t i = 0; i < n; i++)
196  {
197  Object *current = m_aggregates->buffer[i];
198  if (!current->m_initialized)
199  {
200  current->DoInitialize ();
201  current->m_initialized = true;
202  goto restart;
203  }
204  }
205 }
206 void
208 {
217  NS_LOG_FUNCTION (this);
218 restart:
219  uint32_t n = m_aggregates->n;
220  for (uint32_t i = 0; i < n; i++)
221  {
222  Object *current = m_aggregates->buffer[i];
223  if (!current->m_disposed)
224  {
225  current->DoDispose ();
226  current->m_disposed = true;
227  goto restart;
228  }
229  }
230 }
231 void
232 Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
233 {
234  NS_LOG_FUNCTION (this << aggregates << j);
235  while (j > 0 &&
236  aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
237  {
238  Object *tmp = aggregates->buffer[j-1];
239  aggregates->buffer[j-1] = aggregates->buffer[j];
240  aggregates->buffer[j] = tmp;
241  j--;
242  }
243 }
244 void
246 {
247  NS_LOG_FUNCTION (this << o);
249  NS_ASSERT (!o->m_disposed);
250  NS_ASSERT (CheckLoose ());
251  NS_ASSERT (o->CheckLoose ());
252 
253  if (DoGetObject (o->GetInstanceTypeId ()))
254  {
255  NS_FATAL_ERROR ("Object::AggregateObject(): "
256  "Multiple aggregation of objects of type " <<
257  o->GetInstanceTypeId ().GetName ());
258  }
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  UpdateSortedArray (aggregates, m_aggregates->n + i);
277  }
278 
279  // keep track of the old aggregate buffers for the iteration
280  // of NotifyNewAggregates
281  struct Aggregates *a = m_aggregates;
282  struct Aggregates *b = other->m_aggregates;
283 
284  // Then, assign the new aggregation buffer to every object
285  uint32_t n = aggregates->n;
286  for (uint32_t i = 0; i < n; i++)
287  {
288  Object *current = aggregates->buffer[i];
289  current->m_aggregates = aggregates;
290  }
291 
292  // Finally, call NotifyNewAggregate on all the objects aggregates together.
293  // We purposedly use the old aggregate buffers to iterate over the objects
294  // because this allows us to assume that they will not change from under
295  // our feet, even if our users call AggregateObject from within their
296  // NotifyNewAggregate method.
297  for (uint32_t i = 0; i < a->n; i++)
298  {
299  Object *current = a->buffer[i];
300  current->NotifyNewAggregate ();
301  }
302  for (uint32_t i = 0; i < b->n; i++)
303  {
304  Object *current = b->buffer[i];
305  current->NotifyNewAggregate ();
306  }
307 
308  // Now that we are done with them, we can free our old aggregate buffers
309  std::free (a);
310  std::free (b);
311 }
316 void
318 {
319  NS_LOG_FUNCTION (this);
320 }
321 
324 {
325  NS_LOG_FUNCTION (this);
326  return AggregateIterator (this);
327 }
328 
329 void
331 {
332  NS_LOG_FUNCTION (this << tid);
333  NS_ASSERT (Check ());
334  m_tid = tid;
335 }
336 
337 void
339 {
340  NS_LOG_FUNCTION (this);
342 }
343 
344 void
346 {
347  NS_LOG_FUNCTION (this);
349 }
350 
351 bool
352 Object::Check (void) const
353 {
354  NS_LOG_FUNCTION (this);
355  return (GetReferenceCount () > 0);
356 }
357 
358 /* In some cases, when an event is scheduled against a subclass of
359  * Object, and if no one owns a reference directly to this object, the
360  * object is alive, has a refcount of zero and the method ran when the
361  * event expires runs against the raw pointer which means that we are
362  * manipulating an object with a refcount of zero. So, instead we
363  * check the aggregate reference count.
364  */
365 bool
366 Object::CheckLoose (void) const
367 {
368  NS_LOG_FUNCTION (this);
369  uint32_t refcount = 0;
370  uint32_t n = m_aggregates->n;
371  for (uint32_t i = 0; i < n; i++)
372  {
373  Object *current = m_aggregates->buffer[i];
375  refcount += current->GetReferenceCount ();
376  }
377  return (refcount > 0);
378 }
379 void
381 {
382  // check if we really need to die
383  NS_LOG_FUNCTION (this);
384  for (uint32_t i = 0; i < m_aggregates->n; i++)
385  {
386  Object *current = m_aggregates->buffer[i];
387  if (current->GetReferenceCount () > 0)
388  {
389  return;
390  }
391  }
392 
393  // Now, we know that we are alone to use this aggregate so,
394  // we can dispose and delete everything safely.
395 
396  uint32_t n = m_aggregates->n;
397  // Ensure we are disposed.
398  for (uint32_t i = 0; i < n; i++)
399  {
400  Object *current = m_aggregates->buffer[i];
401  if (!current->m_disposed)
402  {
403  current->DoDispose ();
404  }
405  }
406 
407  // Now, actually delete all objects
408  struct Aggregates *aggregates = m_aggregates;
409  for (uint32_t i = 0; i < n; i++)
410  {
411  // There is a trick here: each time we call delete below,
412  // the deleted object is removed from the aggregate buffer
413  // in the destructor so, the index of the next element to
414  // lookup is always zero
415  Object *current = aggregates->buffer[0];
416  delete current;
417  }
418 }
419 } // namespace ns3
420 
bool CheckLoose(void) const
Check if any aggregated Objects have non-zero reference counts.
Definition: object.cc:366
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 "...
virtual ~Object()
Destructor.
Definition: object.cc:106
virtual TypeId GetInstanceTypeId(void) const
Implement the GetInstanceTypeId method defined in ObjectBase.
Definition: object.cc:79
bool Check(void) const
Verify that this Object is still live, by checking it's reference count.
Definition: object.cc:352
void DoDelete(void)
Attempt to delete this Object.
Definition: object.cc:380
#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
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:61
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
Definition: type-id.cc:652
struct Aggregates * m_aggregates
A pointer to an array of 'aggregates'.
Definition: object.h:422
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:338
#define NS_FATAL_ERROR(msg)
Fatal error handling.
Definition: fatal-error.h:100
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
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
void SetTypeId(TypeId tid)
Set the TypeId of this Object.
Definition: object.cc:330
AggregateIterator()
Default constructor, which has no Object.
Definition: object.cc:49
ns3::AttributeValue, ns3::AttributeAccessor and ns3::AttributeChecker declarations.
List of Attribute name, value and checker triples used to construct Objects.
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:245
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:317
uint32_t n
The number of entries in buffer.
Definition: object.h:333
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:79
TypeId m_tid
Identifies the type of this Object instance.
Definition: object.h:404
Object()
Constructor.
Definition: object.cc:95
std::string GetName(void) const
Definition: type-id.cc:685
friend class AggregateIterator
Definition: object.h:316
ns3::Object class declaration, which is the root of the Object hierarchy and Aggregation.
AggregateIterator GetAggregateIterator(void) const
Get an iterator to the Objects aggregated to this one.
Definition: object.cc:323
bool HasNext(void) const
Check if there are more Aggregates to iterate over.
Definition: object.cc:57
static TypeId GetTypeId(void)
Register this type.
Definition: object.cc:86
void Construct(const AttributeConstructionList &attributes)
Initialize all member variables registered as Attributes of this TypeId.
Definition: object.cc:141
void Initialize(void)
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:182
Ptr< Object > DoGetObject(TypeId tid) const
Find an Object of TypeId tid in the aggregates of this Object.
Definition: object.cc:148
A base class which provides memory management and object aggregation.
Definition: object.h:87
Debug message logging.
a unique identifier for an interface.
Definition: type-id.h:51
void UpdateSortedArray(struct Aggregates *aggregates, uint32_t i) const
Keep the list of aggregates in most-recently-used order.
Definition: object.cc:232
TypeId SetParent(TypeId tid)
Definition: type-id.cc:631
void Dispose(void)
Dispose of this Object.
Definition: object.cc:207
Iterate over the Objects aggregated to an ns3::Object.
Definition: object.h:104
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:345
The list of Objects aggregated to this one.
Definition: object.h:331