A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
object.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 INRIA, Gustavo Carneiro
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
18 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20
21#include "object.h"
22
23#include "assert.h"
24#include "attribute.h"
25#include "log.h"
26#include "object-factory.h"
27#include "string.h"
28
29#include <cstdlib>
30#include <cstring>
31#include <sstream>
32#include <vector>
33
40namespace ns3
41{
42
44
45/*********************************************************************
46 * The Object implementation
47 *********************************************************************/
48
50
52 : m_object(nullptr),
53 m_current(0)
54{
55 NS_LOG_FUNCTION(this);
56}
57
58bool
60{
61 NS_LOG_FUNCTION(this);
62 return m_current < m_object->m_aggregates->n;
63}
64
67{
68 NS_LOG_FUNCTION(this);
69 Object* object = m_object->m_aggregates->buffer[m_current];
70 m_current++;
71 return object;
72}
73
75 : m_object(object),
76 m_current(0)
77{
78 NS_LOG_FUNCTION(this << object);
79}
80
83{
84 NS_LOG_FUNCTION(this);
85 return m_tid;
86}
87
90{
91 static TypeId tid = TypeId("ns3::Object").SetParent<ObjectBase>().SetGroupName("Core");
92 return tid;
93}
94
97 m_disposed(false),
98 m_initialized(false),
99 m_aggregates((Aggregates*)std::malloc(sizeof(Aggregates))),
101{
102 NS_LOG_FUNCTION(this);
103 m_aggregates->n = 1;
104 m_aggregates->buffer[0] = this;
105}
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 = nullptr;
130}
131
133 : m_tid(o.m_tid),
134 m_disposed(false),
135 m_initialized(false),
136 m_aggregates((Aggregates*)std::malloc(sizeof(Aggregates))),
137 m_getObjectCount(0)
138{
139 m_aggregates->n = 1;
140 m_aggregates->buffer[0] = this;
141}
142
143void
145{
146 NS_LOG_FUNCTION(this << &attributes);
147 ConstructSelf(attributes);
148}
149
152{
153 NS_LOG_FUNCTION(this << tid);
155
157 TypeId objectTid = Object::GetTypeId();
158 for (uint32_t i = 0; i < n; i++)
159 {
160 Object* current = m_aggregates->buffer[i];
161 TypeId cur = current->GetInstanceTypeId();
162 while (cur != tid && cur != objectTid)
163 {
164 cur = cur.GetParent();
165 }
166 if (cur == tid)
167 {
168 // This is an attempt to 'cache' the result of this lookup.
169 // the idea is that if we perform a lookup for a TypeId on this object,
170 // we are likely to perform the same lookup later so, we make sure
171 // that the aggregate array is sorted by the number of accesses
172 // to each object.
173
174 // first, increment the access count
175 current->m_getObjectCount++;
176 // then, update the sort
178 // finally, return the match
179 return const_cast<Object*>(current);
180 }
181 }
182 return nullptr;
183}
184
185void
187{
196 NS_LOG_FUNCTION(this);
197restart:
199 for (uint32_t i = 0; i < n; i++)
200 {
201 Object* current = m_aggregates->buffer[i];
202 if (!current->m_initialized)
203 {
204 current->DoInitialize();
205 current->m_initialized = true;
206 goto restart;
207 }
208 }
209}
210
211bool
213{
214 NS_LOG_FUNCTION(this);
215 return m_initialized;
216}
217
218void
220{
229 NS_LOG_FUNCTION(this);
230restart:
232 for (uint32_t i = 0; i < n; i++)
233 {
234 Object* current = m_aggregates->buffer[i];
235 if (!current->m_disposed)
236 {
237 current->DoDispose();
238 current->m_disposed = true;
239 goto restart;
240 }
241 }
242}
243
244void
246{
247 NS_LOG_FUNCTION(this << aggregates << j);
248 while (j > 0 &&
249 aggregates->buffer[j]->m_getObjectCount > aggregates->buffer[j - 1]->m_getObjectCount)
250 {
251 Object* tmp = aggregates->buffer[j - 1];
252 aggregates->buffer[j - 1] = aggregates->buffer[j];
253 aggregates->buffer[j] = tmp;
254 j--;
255 }
256}
257
258void
260{
261 NS_LOG_FUNCTION(this << o);
263 NS_ASSERT(!o->m_disposed);
265 NS_ASSERT(o->CheckLoose());
266
267 Object* other = PeekPointer(o);
268 // first create the new aggregate buffer.
269 uint32_t total = m_aggregates->n + other->m_aggregates->n;
270 Aggregates* aggregates =
271 (Aggregates*)std::malloc(sizeof(Aggregates) + (total - 1) * sizeof(Object*));
272 aggregates->n = total;
273
274 // copy our buffer to the new buffer
275 std::memcpy(&aggregates->buffer[0],
276 &m_aggregates->buffer[0],
277 m_aggregates->n * sizeof(Object*));
278
279 // append the other buffer into the new buffer too
280 for (uint32_t i = 0; i < other->m_aggregates->n; i++)
281 {
282 aggregates->buffer[m_aggregates->n + i] = other->m_aggregates->buffer[i];
283 const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId();
284 if (DoGetObject(typeId))
285 {
286 NS_FATAL_ERROR("Object::AggregateObject(): "
287 "Multiple aggregation of objects of type "
288 << other->GetInstanceTypeId() << " on objects of type " << typeId);
289 }
290 UpdateSortedArray(aggregates, m_aggregates->n + i);
291 }
292
293 // keep track of the old aggregate buffers for the iteration
294 // of NotifyNewAggregates
296 Aggregates* b = other->m_aggregates;
297
298 // Then, assign the new aggregation buffer to every object
299 uint32_t n = aggregates->n;
300 for (uint32_t i = 0; i < n; i++)
301 {
302 Object* current = aggregates->buffer[i];
303 current->m_aggregates = aggregates;
304 }
305
306 // Finally, call NotifyNewAggregate on all the objects aggregates together.
307 // We purposely use the old aggregate buffers to iterate over the objects
308 // because this allows us to assume that they will not change from under
309 // our feet, even if our users call AggregateObject from within their
310 // NotifyNewAggregate method.
311 for (uint32_t i = 0; i < a->n; i++)
312 {
313 Object* current = a->buffer[i];
314 current->NotifyNewAggregate();
315 }
316 for (uint32_t i = 0; i < b->n; i++)
317 {
318 Object* current = b->buffer[i];
319 current->NotifyNewAggregate();
320 }
321
322 // Now that we are done with them, we can free our old aggregate buffers
323 std::free(a);
324 std::free(b);
325}
326
331void
333{
334 NS_LOG_FUNCTION(this);
335}
336
339{
340 NS_LOG_FUNCTION(this);
341 return AggregateIterator(this);
342}
343
344void
346{
347 NS_LOG_FUNCTION(this << tid);
348 NS_ASSERT(Check());
349 m_tid = tid;
350}
351
352void
354{
355 NS_LOG_FUNCTION(this);
357}
358
359void
361{
362 NS_LOG_FUNCTION(this);
364}
365
366bool
368{
369 NS_LOG_FUNCTION(this);
370 return (GetReferenceCount() > 0);
371}
372
373/* In some cases, when an event is scheduled against a subclass of
374 * Object, and if no one owns a reference directly to this object, the
375 * object is alive, has a refcount of zero and the method ran when the
376 * event expires runs against the raw pointer which means that we are
377 * manipulating an object with a refcount of zero. So, instead we
378 * check the aggregate reference count.
379 */
380bool
382{
383 NS_LOG_FUNCTION(this);
384 bool nonZeroRefCount = false;
386 for (uint32_t i = 0; i < n; i++)
387 {
388 Object* current = m_aggregates->buffer[i];
389 if (current->GetReferenceCount())
390 {
391 nonZeroRefCount = true;
392 break;
393 }
394 }
395 return nonZeroRefCount;
396}
397
398void
400{
401 // check if we really need to die
402 NS_LOG_FUNCTION(this);
403 for (uint32_t i = 0; i < m_aggregates->n; i++)
404 {
405 Object* current = m_aggregates->buffer[i];
406 if (current->GetReferenceCount() > 0)
407 {
408 return;
409 }
410 }
411
412 // Now, we know that we are alone to use this aggregate so,
413 // we can dispose and delete everything safely.
414
416 // Ensure we are disposed.
417 for (uint32_t i = 0; i < n; i++)
418 {
419 Object* current = m_aggregates->buffer[i];
420 if (!current->m_disposed)
421 {
422 current->DoDispose();
423 }
424 }
425
426 // Now, actually delete all objects
427 Aggregates* aggregates = m_aggregates;
428 for (uint32_t i = 0; i < n; i++)
429 {
430 // There is a trick here: each time we call delete below,
431 // the deleted object is removed from the aggregate buffer
432 // in the destructor so, the index of the next element to
433 // lookup is always zero
434 Object* current = aggregates->buffer[0];
435 delete current;
436 }
437}
438} // namespace ns3
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:106
Ptr< const Object > Next()
Get the next Aggregated Object.
Definition: object.cc:66
AggregateIterator()
Default constructor, which has no Object.
Definition: object.cc:51
bool HasNext() const
Check if there are more Aggregates to iterate over.
Definition: object.cc:59
Anchor the ns-3 type and attribute system.
Definition: object-base.h:173
void ConstructSelf(const AttributeConstructionList &attributes)
Complete construction of ObjectBase; invoked by derived classes.
Definition: object-base.cc:81
A base class which provides memory management and object aggregation.
Definition: object.h:89
Aggregates * m_aggregates
A pointer to an array of 'aggregates'.
Definition: object.h:438
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
void UpdateSortedArray(Aggregates *aggregates, uint32_t i) const
Keep the list of aggregates in most-recently-used order.
Definition: object.cc:245
void Construct(const AttributeConstructionList &attributes)
Initialize all member variables registered as Attributes of this TypeId.
Definition: object.cc:144
bool Check() const
Verify that this Object is still live, by checking it's reference count.
Definition: object.cc:367
Ptr< Object > DoGetObject(TypeId tid) const
Find an Object of TypeId tid in the aggregates of this Object.
Definition: object.cc:151
bool m_disposed
Set to true when the DoDispose() method of the Object has run, false otherwise.
Definition: object.h:425
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:332
bool CheckLoose() const
Check if any aggregated Objects have non-zero reference counts.
Definition: object.cc:381
~Object() override
Destructor.
Definition: object.cc:107
AggregateIterator GetAggregateIterator() const
Get an iterator to the Objects aggregated to this one.
Definition: object.cc:338
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:360
void SetTypeId(TypeId tid)
Set the TypeId of this Object.
Definition: object.cc:345
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: object.cc:82
static TypeId GetTypeId()
Register this type.
Definition: object.cc:89
void Dispose()
Dispose of this Object.
Definition: object.cc:219
TypeId m_tid
Identifies the type of this Object instance.
Definition: object.h:420
Object()
Constructor.
Definition: object.cc:95
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
bool IsInitialized() const
Check if the object has been initialized.
Definition: object.cc:212
uint32_t m_getObjectCount
The number of times the Object was accessed with a call to GetObject().
Definition: object.h:446
void DoDelete()
Attempt to delete this Object.
Definition: object.cc:399
bool m_initialized
Set to true once the DoInitialize() method has run, false otherwise.
Definition: object.h:430
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
uint32_t GetReferenceCount() const
Get the reference count of the object.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId GetParent() const
Get the parent of this TypeId.
Definition: type-id.cc:960
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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:46
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:488
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:347
uint32_t n
The number of entries in buffer.
Definition: object.h:349
Object * buffer[1]
The array of Objects.
Definition: object.h:351