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 "singleton.h"
26 #include "attribute.h"
27 #include "log.h"
28 #include "string.h"
29 #include <vector>
30 #include <sstream>
31 #include <cstdlib>
32 #include <cstring>
33 
34 
35 
36 NS_LOG_COMPONENT_DEFINE ("Object");
37 
38 namespace ns3 {
39 
40 /*********************************************************************
41  * The Object implementation
42  *********************************************************************/
43 
45 
47  : m_object (0),
48  m_current (0)
49 {
50  NS_LOG_FUNCTION (this);
51 }
52 
53 bool
55 {
56  NS_LOG_FUNCTION (this);
57  return m_current < m_object->m_aggregates->n;
58 }
61 {
62  NS_LOG_FUNCTION (this);
63  Object *object = m_object->m_aggregates->buffer[m_current];
64  m_current++;
65  return object;
66 }
68  : m_object (object),
69  m_current (0)
70 {
71  NS_LOG_FUNCTION (this << object);
72 }
73 
74 
75 TypeId
77 {
78  NS_LOG_FUNCTION (this);
79  return m_tid;
80 }
81 
82 TypeId
84 {
85  static TypeId tid = TypeId ("ns3::Object")
87  ;
88  return tid;
89 }
90 
91 
93  : m_tid (Object::GetTypeId ()),
94  m_disposed (false),
95  m_initialized (false),
96  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
98 {
99  NS_LOG_FUNCTION (this);
100  m_aggregates->n = 1;
101  m_aggregates->buffer[0] = this;
102 }
104 {
105  // remove this object from the aggregate list
106  NS_LOG_FUNCTION (this);
107  uint32_t n = m_aggregates->n;
108  for (uint32_t i = 0; i < n; i++)
109  {
111  if (current == this)
112  {
113  std::memmove (&m_aggregates->buffer[i],
114  &m_aggregates->buffer[i+1],
115  sizeof (Object *)*(m_aggregates->n - (i+1)));
116  m_aggregates->n--;
117  }
118  }
119  // finally, if all objects have been removed from the list,
120  // delete the aggregate list
121  if (m_aggregates->n == 0)
122  {
123  std::free (m_aggregates);
124  }
125  m_aggregates = 0;
126 }
128  : m_tid (o.m_tid),
129  m_disposed (false),
130  m_initialized (false),
131  m_aggregates ((struct Aggregates *) std::malloc (sizeof (struct Aggregates))),
132  m_getObjectCount (0)
133 {
134  m_aggregates->n = 1;
135  m_aggregates->buffer[0] = this;
136 }
137 void
139 {
140  NS_LOG_FUNCTION (this << &attributes);
141  ConstructSelf (attributes);
142 }
143 
146 {
147  NS_LOG_FUNCTION (this << tid);
148  NS_ASSERT (CheckLoose ());
149 
150  uint32_t n = m_aggregates->n;
151  TypeId objectTid = Object::GetTypeId ();
152  for (uint32_t i = 0; i < n; i++)
153  {
155  TypeId cur = current->GetInstanceTypeId ();
156  while (cur != tid && cur != objectTid)
157  {
158  cur = cur.GetParent ();
159  }
160  if (cur == tid)
161  {
162  // This is an attempt to 'cache' the result of this lookup.
163  // the idea is that if we perform a lookup for a TypeId on this object,
164  // we are likely to perform the same lookup later so, we make sure
165  // that the aggregate array is sorted by the number of accesses
166  // to each object.
167 
168  // first, increment the access count
169  current->m_getObjectCount++;
170  // then, update the sort
172  // finally, return the match
173  return const_cast<Object *> (current);
174  }
175  }
176  return 0;
177 }
178 void
180 {
189  NS_LOG_FUNCTION (this);
190 restart:
191  uint32_t n = m_aggregates->n;
192  for (uint32_t i = 0; i < n; i++)
193  {
195  if (!current->m_initialized)
196  {
197  current->DoInitialize ();
198  current->m_initialized = true;
199  goto restart;
200  }
201  }
202 }
203 void
205 {
214  NS_LOG_FUNCTION (this);
215 restart:
216  uint32_t n = m_aggregates->n;
217  for (uint32_t i = 0; i < n; i++)
218  {
220  if (!current->m_disposed)
221  {
222  current->DoDispose ();
223  current->m_disposed = true;
224  goto restart;
225  }
226  }
227 }
228 void
229 Object::UpdateSortedArray (struct Aggregates *aggregates, uint32_t j) const
230 {
231  NS_LOG_FUNCTION (this << aggregates << j);
232  while (j > 0 &&
233  aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j-1]->m_getObjectCount)
234  {
235  Object *tmp = aggregates->buffer[j-1];
236  aggregates->buffer[j-1] = aggregates->buffer[j];
237  aggregates->buffer[j] = tmp;
238  j--;
239  }
240 }
241 void
243 {
244  NS_LOG_FUNCTION (this << o);
246  NS_ASSERT (!o->m_disposed);
247  NS_ASSERT (CheckLoose ());
248  NS_ASSERT (o->CheckLoose ());
249 
250  if (DoGetObject (o->GetInstanceTypeId ()))
251  {
252  NS_FATAL_ERROR ("Object::AggregateObject(): "
253  "Multiple aggregation of objects of type " <<
254  o->GetInstanceTypeId ().GetName ());
255  }
256 
257  Object *other = PeekPointer (o);
258  // first create the new aggregate buffer.
259  uint32_t total = m_aggregates->n + other->m_aggregates->n;
260  struct Aggregates *aggregates =
261  (struct Aggregates *)std::malloc (sizeof(struct Aggregates)+(total-1)*sizeof(Object*));
262  aggregates->n = total;
263 
264  // copy our buffer to the new buffer
265  std::memcpy (&aggregates->buffer[0],
266  &m_aggregates->buffer[0],
267  m_aggregates->n*sizeof(Object*));
268 
269  // append the other buffer into the new buffer too
270  for (uint32_t i = 0; i < other->m_aggregates->n; i++)
271  {
272  aggregates->buffer[m_aggregates->n+i] = other->m_aggregates->buffer[i];
273  UpdateSortedArray (aggregates, m_aggregates->n + i);
274  }
275 
276  // keep track of the old aggregate buffers for the iteration
277  // of NotifyNewAggregates
278  struct Aggregates *a = m_aggregates;
279  struct Aggregates *b = other->m_aggregates;
280 
281  // Then, assign the new aggregation buffer to every object
282  uint32_t n = aggregates->n;
283  for (uint32_t i = 0; i < n; i++)
284  {
285  Object *current = aggregates->buffer[i];
286  current->m_aggregates = aggregates;
287  }
288 
289  // Finally, call NotifyNewAggregate on all the objects aggregates together.
290  // We purposedly use the old aggregate buffers to iterate over the objects
291  // because this allows us to assume that they will not change from under
292  // our feet, even if our users call AggregateObject from within their
293  // NotifyNewAggregate method.
294  for (uint32_t i = 0; i < a->n; i++)
295  {
296  Object *current = a->buffer[i];
297  current->NotifyNewAggregate ();
298  }
299  for (uint32_t i = 0; i < b->n; i++)
300  {
301  Object *current = b->buffer[i];
302  current->NotifyNewAggregate ();
303  }
304 
305  // Now that we are done with them, we can free our old aggregate buffers
306  std::free (a);
307  std::free (b);
308 }
313 void
315 {
316  NS_LOG_FUNCTION (this);
317 }
318 
321 {
322  NS_LOG_FUNCTION (this);
323  return AggregateIterator (this);
324 }
325 
326 void
328 {
329  NS_LOG_FUNCTION (this << tid);
330  NS_ASSERT (Check ());
331  m_tid = tid;
332 }
333 
334 void
336 {
337  NS_LOG_FUNCTION (this);
339 }
340 
341 void
343 {
344  NS_LOG_FUNCTION (this);
346 }
347 
348 bool
349 Object::Check (void) const
350 {
351  NS_LOG_FUNCTION (this);
352  return (GetReferenceCount () > 0);
353 }
354 
355 /* In some cases, when an event is scheduled against a subclass of
356  * Object, and if no one owns a reference directly to this object, the
357  * object is alive, has a refcount of zero and the method ran when the
358  * event expires runs against the raw pointer which means that we are
359  * manipulating an object with a refcount of zero. So, instead we
360  * check the aggregate reference count.
361  */
362 bool
363 Object::CheckLoose (void) const
364 {
365  NS_LOG_FUNCTION (this);
366  uint32_t refcount = 0;
367  uint32_t n = m_aggregates->n;
368  for (uint32_t i = 0; i < n; i++)
369  {
371  refcount += current->GetReferenceCount ();
372  }
373  return (refcount > 0);
374 }
375 void
377 {
378  // check if we really need to die
379  NS_LOG_FUNCTION (this);
380  for (uint32_t i = 0; i < m_aggregates->n; i++)
381  {
383  if (current->GetReferenceCount () > 0)
384  {
385  return;
386  }
387  }
388 
389  // Now, we know that we are alone to use this aggregate so,
390  // we can dispose and delete everything safely.
391 
392  uint32_t n = m_aggregates->n;
393  // Ensure we are disposed.
394  for (uint32_t i = 0; i < n; i++)
395  {
397  if (!current->m_disposed)
398  {
399  current->DoDispose ();
400  }
401  }
402 
403  // Now, actually delete all objects
404  struct Aggregates *aggregates = m_aggregates;
405  for (uint32_t i = 0; i < n; i++)
406  {
407  // There is a trick here: each time we call delete below,
408  // the deleted object is removed from the aggregate buffer
409  // in the destructor so, the index of the next element to
410  // lookup is always zero
411  Object *current = aggregates->buffer[0];
412  delete current;
413  }
414 }
415 } // namespace ns3
416 
bool CheckLoose(void) const
Definition: object.cc:363
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual ~Object()
Definition: object.cc:103
virtual TypeId GetInstanceTypeId(void) const
Definition: object.cc:76
bool Check(void) const
Definition: object.cc:349
void DoDelete(void)
Attempt to delete this object.
Definition: object.cc:376
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
bool m_disposed
Set to true when the DoDispose method of the object has run, false otherwise.
Definition: object.h:312
uint32_t m_getObjectCount
Indicates the number of times the object was accessed with a call to GetObject.
Definition: object.h:331
#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
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
TypeId GetParent(void) const
Definition: type-id.cc:624
struct Aggregates * m_aggregates
a pointer to an array of 'aggregates'.
Definition: object.h:324
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: object.cc:335
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
implement the ns-3 type and attribute system
Definition: object-base.h:61
bool m_initialized
Set to true once the DoInitialize method has run, false otherwise.
Definition: object.h:317
Object * buffer[1]
Definition: object.h:246
uint32_t GetReferenceCount(void) const
Get the reference count of the object.
Ptr< const Object > Next(void)
Definition: object.cc:60
void SetTypeId(TypeId tid)
Definition: object.cc:327
T * PeekPointer(const Ptr< T > &p)
Definition: ptr.h:280
void AggregateObject(Ptr< Object > other)
Definition: object.cc:242
virtual void NotifyNewAggregate(void)
This method is invoked whenever two sets of objects are aggregated together.
Definition: object.cc:314
void ConstructSelf(const AttributeConstructionList &attributes)
Definition: object-base.cc:65
TypeId m_tid
Identifies the type of this object instance.
Definition: object.h:307
std::string GetName(void) const
Definition: type-id.cc:657
friend class AggregateIterator
Definition: object.h:231
AggregateIterator GetAggregateIterator(void) const
Definition: object.cc:320
Time current
bool HasNext(void) const
Definition: object.cc:54
static TypeId GetTypeId(void)
Register this type.
Definition: object.cc:83
void Construct(const AttributeConstructionList &attributes)
Definition: object.cc:138
void Initialize(void)
This method calls the virtual DoInitialize method on all the objects aggregated to this object...
Definition: object.cc:179
Ptr< Object > DoGetObject(TypeId tid) const
Find an object of TypeId tid in the aggregates of this Object.
Definition: object.cc:145
a base class which provides memory management and object aggregation
Definition: object.h:64
a unique identifier for an interface.
Definition: type-id.h:49
void UpdateSortedArray(struct Aggregates *aggregates, uint32_t i) const
Keep the list of aggregates in most-recently-used order.
Definition: object.cc:229
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void Dispose(void)
Run the DoDispose methods of this object and all the objects aggregated to it.
Definition: object.cc:204
Iterate over the objects aggregated to an ns3::Object.
Definition: object.h:81
virtual void DoInitialize(void)
This method is called only once by Object::Initialize.
Definition: object.cc:342
This data structure uses a classic C-style trick to hold an array of variable size without performing...
Definition: object.h:244