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
39namespace ns3 {
40
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
56bool
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
80{
81 NS_LOG_FUNCTION (this);
82 return m_tid;
83}
84
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))),
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);
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}
141void
143{
144 NS_LOG_FUNCTION (this << &attributes);
145 ConstructSelf (attributes);
146}
147
150{
151 NS_LOG_FUNCTION (this << tid);
153
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}
182void
184{
193 NS_LOG_FUNCTION (this);
194restart:
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}
207bool
209{
210 NS_LOG_FUNCTION (this);
211 return m_initialized;
212}
213void
215{
224 NS_LOG_FUNCTION (this);
225restart:
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}
238void
239Object::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}
251void
253{
254 NS_LOG_FUNCTION (this << o);
256 NS_ASSERT (!o->m_disposed);
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}
324void
326{
327 NS_LOG_FUNCTION (this);
328}
329
332{
333 NS_LOG_FUNCTION (this);
334 return AggregateIterator (this);
335}
336
337void
339{
340 NS_LOG_FUNCTION (this << tid);
341 NS_ASSERT (Check ());
342 m_tid = tid;
343}
344
345void
347{
348 NS_LOG_FUNCTION (this);
350}
351
352void
354{
355 NS_LOG_FUNCTION (this);
357}
358
359bool
360Object::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 */
373bool
375{
376 NS_LOG_FUNCTION (this);
377 bool nonZeroRefCount = false;
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}
390void
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
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
STL namespace.
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