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
#include "
object.h
"
22
#include "
object-factory.h
"
23
#include "
assert.h
"
24
#include "
singleton.h
"
25
#include "
attribute.h
"
26
#include "
log.h
"
27
#include "
string.h
"
28
#include <vector>
29
#include <sstream>
30
#include <stdlib.h>
31
#include <
string.h
>
32
33
NS_LOG_COMPONENT_DEFINE
(
"Object"
);
34
35
namespace
ns3 {
36
37
/*********************************************************************
38
* The Object implementation
39
*********************************************************************/
40
41
NS_OBJECT_ENSURE_REGISTERED
(Object);
42
43
Object::AggregateIterator::AggregateIterator
()
44
: m_object (0),
45
m_current (0)
46
{
47
}
48
49
bool
50
Object::AggregateIterator::HasNext
(
void
)
const
51
{
52
return
m_current < m_object->m_aggregates->n;
53
}
54
Ptr<const Object>
55
Object::AggregateIterator::Next
(
void
)
56
{
57
Object
*
object
= m_object->
m_aggregates
->
buffer
[m_current];
58
m_current++;
59
return
object;
60
}
61
Object::AggregateIterator::AggregateIterator
(
Ptr<const Object>
object
)
62
: m_object (object),
63
m_current (0)
64
{
65
}
66
67
68
TypeId
69
Object::GetInstanceTypeId
(
void
)
const
70
{
71
return
m_tid
;
72
}
73
74
TypeId
75
Object::GetTypeId
(
void
)
76
{
77
static
TypeId
tid =
TypeId
(
"ns3::Object"
)
78
.
SetParent
<
ObjectBase
> ()
79
;
80
return
tid;
81
}
82
83
84
Object::Object
()
85
:
m_tid
(
Object
::
GetTypeId
()),
86
m_disposed
(false),
87
m_started
(false),
88
m_aggregates
((struct
Aggregates
*) malloc (sizeof (struct
Aggregates
))),
89
m_getObjectCount
(0)
90
{
91
m_aggregates
->
n
= 1;
92
m_aggregates
->
buffer
[0] =
this
;
93
}
94
Object::~Object
()
95
{
96
// remove this object from the aggregate list
97
uint32_t n =
m_aggregates
->
n
;
98
for
(uint32_t i = 0; i < n; i++)
99
{
100
Object
*current =
m_aggregates
->
buffer
[i];
101
if
(current ==
this
)
102
{
103
memmove (&
m_aggregates
->
buffer
[i],
104
&
m_aggregates
->
buffer
[i+1],
105
sizeof (
Object
*)*(
m_aggregates
->
n
- (i+1)));
106
m_aggregates
->
n
--;
107
}
108
}
109
// finally, if all objects have been removed from the list,
110
// delete the aggregate list
111
if
(
m_aggregates
->
n
== 0)
112
{
113
free (
m_aggregates
);
114
}
115
m_aggregates
= 0;
116
}
117
Object::Object
(
const
Object
&o)
118
: m_tid (o.m_tid),
119
m_disposed (false),
120
m_started (false),
121
m_aggregates ((struct
Aggregates
*) malloc (sizeof (struct
Aggregates
))),
122
m_getObjectCount (0)
123
{
124
m_aggregates
->
n
= 1;
125
m_aggregates
->
buffer
[0] =
this
;
126
}
127
void
128
Object::Construct
(
const
AttributeConstructionList
&attributes)
129
{
130
ConstructSelf
(attributes);
131
}
132
133
Ptr<Object>
134
Object::DoGetObject
(
TypeId
tid)
const
135
{
136
NS_ASSERT
(
CheckLoose
());
137
138
uint32_t n =
m_aggregates
->
n
;
139
TypeId
objectTid =
Object::GetTypeId
();
140
for
(uint32_t i = 0; i < n; i++)
141
{
142
Object
*current =
m_aggregates
->
buffer
[i];
143
TypeId
cur = current->
GetInstanceTypeId
();
144
while
(cur != tid && cur != objectTid)
145
{
146
cur = cur.
GetParent
();
147
}
148
if
(cur == tid)
149
{
150
// This is an attempt to 'cache' the result of this lookup.
151
// the idea is that if we perform a lookup for a TypeId on this object,
152
// we are likely to perform the same lookup later so, we make sure
153
// that the aggregate array is sorted by the number of accesses
154
// to each object.
155
156
// first, increment the access count
157
current->
m_getObjectCount
++;
158
// then, update the sort
159
UpdateSortedArray
(
m_aggregates
, i);
160
// finally, return the match
161
return
const_cast<
Object
*
>
(current);
162
}
163
}
164
return
0;
165
}
166
void
167
Object::Start
(
void
)
168
{
177
restart:
178
uint32_t n =
m_aggregates
->
n
;
179
for
(uint32_t i = 0; i < n; i++)
180
{
181
Object
*current =
m_aggregates
->
buffer
[i];
182
if
(!current->
m_started
)
183
{
184
current->
DoStart
();
185
current->
m_started
=
true
;
186
goto
restart;
187
}
188
}
189
}
190
void
191
Object::Dispose
(
void
)
192
{
201
restart:
202
uint32_t n =
m_aggregates
->
n
;
203
for
(uint32_t i = 0; i < n; i++)
204
{
205
Object
*current =
m_aggregates
->
buffer
[i];
206
if
(!current->
m_disposed
)
207
{
208
current->
DoDispose
();
209
current->
m_disposed
=
true
;
210
goto
restart;
211
}
212
}
213
}
214
void
215
Object::UpdateSortedArray
(
struct
Aggregates
*aggregates, uint32_t j)
const
216
{
217
while
(j > 0 &&
218
aggregates->
buffer
[j]->
m_getObjectCount
> aggregates->
buffer
[j-1]->
m_getObjectCount
)
219
{
220
Object
*tmp = aggregates->
buffer
[j-1];
221
aggregates->
buffer
[j-1] = aggregates->
buffer
[j];
222
aggregates->
buffer
[j] = tmp;
223
j--;
224
}
225
}
226
void
227
Object::AggregateObject
(
Ptr<Object>
o)
228
{
229
NS_ASSERT
(!
m_disposed
);
230
NS_ASSERT
(!o->
m_disposed
);
231
NS_ASSERT
(
CheckLoose
());
232
NS_ASSERT
(o->
CheckLoose
());
233
234
if
(
DoGetObject
(o->
GetInstanceTypeId
()))
235
{
236
NS_FATAL_ERROR
(
"Object::AggregateObject(): "
237
"Multiple aggregation of objects of type "
<<
238
o->
GetInstanceTypeId
().
GetName
());
239
}
240
241
Object
*other =
PeekPointer
(o);
242
// first create the new aggregate buffer.
243
uint32_t total =
m_aggregates
->
n
+ other->
m_aggregates
->
n
;
244
struct
Aggregates
*aggregates =
245
(
struct
Aggregates
*)malloc (
sizeof
(
struct
Aggregates
)+(total-1)*
sizeof
(
Object
*));
246
aggregates->
n
= total;
247
248
// copy our buffer to the new buffer
249
memcpy (&aggregates->
buffer
[0],
250
&
m_aggregates
->
buffer
[0],
251
m_aggregates
->
n
*
sizeof
(
Object
*));
252
253
// append the other buffer into the new buffer too
254
for
(uint32_t i = 0; i < other->
m_aggregates
->
n
; i++)
255
{
256
aggregates->
buffer
[
m_aggregates
->
n
+i] = other->
m_aggregates
->
buffer
[i];
257
UpdateSortedArray
(aggregates,
m_aggregates
->
n
+ i);
258
}
259
260
// keep track of the old aggregate buffers for the iteration
261
// of NotifyNewAggregates
262
struct
Aggregates
*a =
m_aggregates
;
263
struct
Aggregates
*b = other->
m_aggregates
;
264
265
// Then, assign the new aggregation buffer to every object
266
uint32_t n = aggregates->
n
;
267
for
(uint32_t i = 0; i < n; i++)
268
{
269
Object
*current = aggregates->
buffer
[i];
270
current->
m_aggregates
= aggregates;
271
}
272
273
// Finally, call NotifyNewAggregate on all the objects aggregates together.
274
// We purposedly use the old aggregate buffers to iterate over the objects
275
// because this allows us to assume that they will not change from under
276
// our feet, even if our users call AggregateObject from within their
277
// NotifyNewAggregate method.
278
for
(uint32_t i = 0; i < a->
n
; i++)
279
{
280
Object
*current = a->
buffer
[i];
281
current->
NotifyNewAggregate
();
282
}
283
for
(uint32_t i = 0; i < b->
n
; i++)
284
{
285
Object
*current = b->
buffer
[i];
286
current->
NotifyNewAggregate
();
287
}
288
289
// Now that we are done with them, we can free our old aggregate buffers
290
free (a);
291
free (b);
292
}
297
void
298
Object::NotifyNewAggregate
()
299
{
300
301
}
302
303
Object::AggregateIterator
304
Object::GetAggregateIterator
(
void
)
const
305
{
306
return
AggregateIterator
(
this
);
307
}
308
309
void
310
Object::SetTypeId
(
TypeId
tid)
311
{
312
NS_ASSERT
(
Check
());
313
m_tid
= tid;
314
}
315
316
void
317
Object::DoDispose
(
void
)
318
{
319
NS_ASSERT
(!
m_disposed
);
320
}
321
322
void
323
Object::DoStart
(
void
)
324
{
325
NS_ASSERT
(!
m_started
);
326
}
327
328
bool
329
Object::Check
(
void
)
const
330
{
331
return
(
GetReferenceCount
() > 0);
332
}
333
334
/* In some cases, when an event is scheduled against a subclass of
335
* Object, and if no one owns a reference directly to this object, the
336
* object is alive, has a refcount of zero and the method ran when the
337
* event expires runs against the raw pointer which means that we are
338
* manipulating an object with a refcount of zero. So, instead we
339
* check the aggregate reference count.
340
*/
341
bool
342
Object::CheckLoose
(
void
)
const
343
{
344
uint32_t refcount = 0;
345
uint32_t n =
m_aggregates
->
n
;
346
for
(uint32_t i = 0; i < n; i++)
347
{
348
Object
*current =
m_aggregates
->
buffer
[i];
349
refcount += current->
GetReferenceCount
();
350
}
351
return
(refcount > 0);
352
}
353
void
354
Object::DoDelete
(
void
)
355
{
356
// check if we really need to die
357
for
(uint32_t i = 0; i <
m_aggregates
->
n
; i++)
358
{
359
Object
*current =
m_aggregates
->
buffer
[i];
360
if
(current->
GetReferenceCount
() > 0)
361
{
362
return
;
363
}
364
}
365
366
// Now, we know that we are alone to use this aggregate so,
367
// we can dispose and delete everything safely.
368
369
uint32_t n =
m_aggregates
->
n
;
370
// Ensure we are disposed.
371
for
(uint32_t i = 0; i < n; i++)
372
{
373
Object
*current =
m_aggregates
->
buffer
[i];
374
if
(!current->
m_disposed
)
375
{
376
current->
DoDispose
();
377
}
378
}
379
380
// Now, actually delete all objects
381
struct
Aggregates
*aggregates =
m_aggregates
;
382
for
(uint32_t i = 0; i < n; i++)
383
{
384
// There is a trick here: each time we call delete below,
385
// the deleted object is removed from the aggregate buffer
386
// in the destructor so, the index of the next element to
387
// lookup is always zero
388
Object
*current = aggregates->
buffer
[0];
389
delete
current;
390
}
391
}
392
}
// namespace ns3
393
src
core
model
object.cc
Generated on Tue Nov 13 2012 10:32:10 for ns-3 by
1.8.1.2