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