A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
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
44
NS_OBJECT_ENSURE_REGISTERED
(Object);
45
46
Object::AggregateIterator::AggregateIterator
()
47
: m_object (0),
48
m_current (0)
49
{
50
NS_LOG_FUNCTION
(
this
);
51
}
52
53
bool
54
Object::AggregateIterator::HasNext
(
void
)
const
55
{
56
NS_LOG_FUNCTION
(
this
);
57
return
m_current < m_object->m_aggregates->n;
58
}
59
Ptr<const Object>
60
Object::AggregateIterator::Next
(
void
)
61
{
62
NS_LOG_FUNCTION
(
this
);
63
Object
*
object
= m_object->
m_aggregates
->
buffer
[m_current];
64
m_current++;
65
return
object;
66
}
67
Object::AggregateIterator::AggregateIterator
(
Ptr<const Object>
object
)
68
: m_object (object),
69
m_current (0)
70
{
71
NS_LOG_FUNCTION
(
this
<<
object
);
72
}
73
74
75
TypeId
76
Object::GetInstanceTypeId
(
void
)
const
77
{
78
NS_LOG_FUNCTION
(
this
);
79
return
m_tid
;
80
}
81
82
TypeId
83
Object::GetTypeId
(
void
)
84
{
85
static
TypeId
tid =
TypeId
(
"ns3::Object"
)
86
.
SetParent
<
ObjectBase
> ()
87
;
88
return
tid;
89
}
90
91
92
Object::Object
()
93
:
m_tid
(
Object
::
GetTypeId
()),
94
m_disposed
(false),
95
m_initialized
(false),
96
m_aggregates
((struct
Aggregates
*) std::malloc (sizeof (struct
Aggregates
))),
97
m_getObjectCount
(0)
98
{
99
NS_LOG_FUNCTION
(
this
);
100
m_aggregates
->
n
= 1;
101
m_aggregates
->
buffer
[0] =
this
;
102
}
103
Object::~Object
()
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
{
110
Object
*current =
m_aggregates
->
buffer
[i];
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
}
127
Object::Object
(
const
Object
&o)
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
138
Object::Construct
(
const
AttributeConstructionList
&attributes)
139
{
140
NS_LOG_FUNCTION
(
this
<< &attributes);
141
ConstructSelf
(attributes);
142
}
143
144
Ptr<Object>
145
Object::DoGetObject
(
TypeId
tid)
const
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
{
154
Object
*current =
m_aggregates
->
buffer
[i];
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
171
UpdateSortedArray
(
m_aggregates
, i);
172
// finally, return the match
173
return
const_cast<
Object
*
>
(current);
174
}
175
}
176
return
0;
177
}
178
void
179
Object::Initialize
(
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
{
194
Object
*current =
m_aggregates
->
buffer
[i];
195
if
(!current->
m_initialized
)
196
{
197
current->
DoInitialize
();
198
current->
m_initialized
=
true
;
199
goto
restart;
200
}
201
}
202
}
203
void
204
Object::Dispose
(
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
{
219
Object
*current =
m_aggregates
->
buffer
[i];
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
242
Object::AggregateObject
(
Ptr<Object>
o)
243
{
244
NS_LOG_FUNCTION
(
this
<< o);
245
NS_ASSERT
(!
m_disposed
);
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
314
Object::NotifyNewAggregate
()
315
{
316
NS_LOG_FUNCTION
(
this
);
317
}
318
319
Object::AggregateIterator
320
Object::GetAggregateIterator
(
void
)
const
321
{
322
NS_LOG_FUNCTION
(
this
);
323
return
AggregateIterator
(
this
);
324
}
325
326
void
327
Object::SetTypeId
(
TypeId
tid)
328
{
329
NS_LOG_FUNCTION
(
this
<< tid);
330
NS_ASSERT
(
Check
());
331
m_tid
= tid;
332
}
333
334
void
335
Object::DoDispose
(
void
)
336
{
337
NS_LOG_FUNCTION
(
this
);
338
NS_ASSERT
(!
m_disposed
);
339
}
340
341
void
342
Object::DoInitialize
(
void
)
343
{
344
NS_LOG_FUNCTION
(
this
);
345
NS_ASSERT
(!
m_initialized
);
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
{
370
Object
*current =
m_aggregates
->
buffer
[i];
371
refcount += current->
GetReferenceCount
();
372
}
373
return
(refcount > 0);
374
}
375
void
376
Object::DoDelete
(
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
{
382
Object
*current =
m_aggregates
->
buffer
[i];
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
{
396
Object
*current =
m_aggregates
->
buffer
[i];
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
src
core
model
object.cc
Generated on Tue May 14 2013 11:08:18 for ns-3 by
1.8.1.2