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
default-simulator-impl.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2005,2006 INRIA
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
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
*/
20
21
#include "
simulator.h
"
22
#include "
default-simulator-impl.h
"
23
#include "
scheduler.h
"
24
#include "
event-impl.h
"
25
26
#include "
ptr.h
"
27
#include "
pointer.h
"
28
#include "
assert.h
"
29
#include "
log.h
"
30
31
#include <math.h>
32
33
NS_LOG_COMPONENT_DEFINE
(
"DefaultSimulatorImpl"
);
34
35
namespace
ns3 {
36
37
NS_OBJECT_ENSURE_REGISTERED
(DefaultSimulatorImpl);
38
39
TypeId
40
DefaultSimulatorImpl::GetTypeId
(
void
)
41
{
42
static
TypeId
tid =
TypeId
(
"ns3::DefaultSimulatorImpl"
)
43
.
SetParent
<
SimulatorImpl
> ()
44
.AddConstructor<DefaultSimulatorImpl> ()
45
;
46
return
tid;
47
}
48
49
DefaultSimulatorImpl::DefaultSimulatorImpl
()
50
{
51
m_stop
=
false
;
52
// uids are allocated from 4.
53
// uid 0 is "invalid" events
54
// uid 1 is "now" events
55
// uid 2 is "destroy" events
56
m_uid
= 4;
57
// before ::Run is entered, the m_currentUid will be zero
58
m_currentUid
= 0;
59
m_currentTs
= 0;
60
m_currentContext
= 0xffffffff;
61
m_unscheduledEvents
= 0;
62
m_eventsWithContextEmpty
=
true
;
63
m_main
=
SystemThread::Self
();
64
}
65
66
DefaultSimulatorImpl::~DefaultSimulatorImpl
()
67
{
68
}
69
70
void
71
DefaultSimulatorImpl::DoDispose
(
void
)
72
{
73
while
(!
m_events
->
IsEmpty
())
74
{
75
Scheduler::Event
next =
m_events
->
RemoveNext
();
76
next.
impl
->
Unref
();
77
}
78
m_events
= 0;
79
SimulatorImpl::DoDispose
();
80
}
81
void
82
DefaultSimulatorImpl::Destroy
()
83
{
84
while
(!
m_destroyEvents
.empty ())
85
{
86
Ptr<EventImpl>
ev =
m_destroyEvents
.front ().PeekEventImpl ();
87
m_destroyEvents
.pop_front ();
88
NS_LOG_LOGIC
(
"handle destroy "
<< ev);
89
if
(!ev->
IsCancelled
())
90
{
91
ev->
Invoke
();
92
}
93
}
94
}
95
96
void
97
DefaultSimulatorImpl::SetScheduler
(
ObjectFactory
schedulerFactory)
98
{
99
Ptr<Scheduler>
scheduler = schedulerFactory.
Create
<
Scheduler
> ();
100
101
if
(
m_events
!= 0)
102
{
103
while
(!
m_events
->
IsEmpty
())
104
{
105
Scheduler::Event
next =
m_events
->
RemoveNext
();
106
scheduler->
Insert
(next);
107
}
108
}
109
m_events
= scheduler;
110
}
111
112
// System ID for non-distributed simulation is always zero
113
uint32_t
114
DefaultSimulatorImpl::GetSystemId
(
void
)
const
115
{
116
return
0;
117
}
118
119
void
120
DefaultSimulatorImpl::ProcessOneEvent
(
void
)
121
{
122
Scheduler::Event
next =
m_events
->
RemoveNext
();
123
124
NS_ASSERT
(next.
key
.
m_ts
>=
m_currentTs
);
125
m_unscheduledEvents
--;
126
127
NS_LOG_LOGIC
(
"handle "
<< next.
key
.
m_ts
);
128
m_currentTs
= next.
key
.
m_ts
;
129
m_currentContext
= next.
key
.
m_context
;
130
m_currentUid
= next.
key
.
m_uid
;
131
next.
impl
->
Invoke
();
132
next.
impl
->
Unref
();
133
134
ProcessEventsWithContext
();
135
}
136
137
bool
138
DefaultSimulatorImpl::IsFinished
(
void
)
const
139
{
140
return
m_events
->
IsEmpty
() ||
m_stop
;
141
}
142
143
void
144
DefaultSimulatorImpl::ProcessEventsWithContext
(
void
)
145
{
146
if
(
m_eventsWithContextEmpty
)
147
{
148
return
;
149
}
150
151
// swap queues
152
EventsWithContext
eventsWithContext;
153
{
154
CriticalSection
cs (
m_eventsWithContextMutex
);
155
m_eventsWithContext
.swap(eventsWithContext);
156
m_eventsWithContextEmpty
=
true
;
157
}
158
while
(!eventsWithContext.empty ())
159
{
160
EventWithContext
event
= eventsWithContext.front ();
161
eventsWithContext.pop_front ();
162
Scheduler::Event
ev;
163
ev.
impl
=
event
.event;
164
ev.
key
.
m_ts
=
m_currentTs
+
event
.timestamp;
165
ev.
key
.
m_context
=
event
.context;
166
ev.
key
.
m_uid
=
m_uid
;
167
m_uid
++;
168
m_unscheduledEvents
++;
169
m_events
->
Insert
(ev);
170
}
171
}
172
173
void
174
DefaultSimulatorImpl::Run
(
void
)
175
{
176
// Set the current threadId as the main threadId
177
m_main
=
SystemThread::Self
();
178
ProcessEventsWithContext
();
179
m_stop
=
false
;
180
181
while
(!
m_events
->
IsEmpty
() && !
m_stop
)
182
{
183
ProcessOneEvent
();
184
}
185
186
// If the simulator stopped naturally by lack of events, make a
187
// consistency test to check that we didn't lose any events along the way.
188
NS_ASSERT
(!
m_events
->
IsEmpty
() ||
m_unscheduledEvents
== 0);
189
}
190
191
void
192
DefaultSimulatorImpl::Stop
(
void
)
193
{
194
m_stop
=
true
;
195
}
196
197
void
198
DefaultSimulatorImpl::Stop
(
Time
const
&time)
199
{
200
Simulator::Schedule
(time, &
Simulator::Stop
);
201
}
202
203
//
204
// Schedule an event for a _relative_ time in the future.
205
//
206
EventId
207
DefaultSimulatorImpl::Schedule
(
Time
const
&time,
EventImpl
*event)
208
{
209
NS_ASSERT_MSG
(
SystemThread::Equals
(
m_main
),
"Simulator::Schedule Thread-unsafe invocation!"
);
210
211
Time
tAbsolute = time +
TimeStep
(
m_currentTs
);
212
213
NS_ASSERT
(tAbsolute.
IsPositive
());
214
NS_ASSERT
(tAbsolute >= TimeStep (
m_currentTs
));
215
Scheduler::Event
ev;
216
ev.
impl
= event;
217
ev.
key
.
m_ts
= (uint64_t) tAbsolute.
GetTimeStep
();
218
ev.
key
.
m_context
=
GetContext
();
219
ev.
key
.
m_uid
=
m_uid
;
220
m_uid
++;
221
m_unscheduledEvents
++;
222
m_events
->
Insert
(ev);
223
return
EventId
(event, ev.
key
.
m_ts
, ev.
key
.
m_context
, ev.
key
.
m_uid
);
224
}
225
226
void
227
DefaultSimulatorImpl::ScheduleWithContext
(uint32_t context,
Time
const
&time,
EventImpl
*event)
228
{
229
NS_LOG_FUNCTION
(
this
<< context << time.
GetTimeStep
() <<
m_currentTs
<< event);
230
231
if
(
SystemThread::Equals
(
m_main
))
232
{
233
Time
tAbsolute = time +
TimeStep
(
m_currentTs
);
234
Scheduler::Event
ev;
235
ev.
impl
= event;
236
ev.
key
.
m_ts
= (uint64_t) tAbsolute.
GetTimeStep
();
237
ev.
key
.
m_context
= context;
238
ev.
key
.
m_uid
=
m_uid
;
239
m_uid
++;
240
m_unscheduledEvents
++;
241
m_events
->
Insert
(ev);
242
}
243
else
244
{
245
EventWithContext
ev;
246
ev.
context
= context;
247
ev.
timestamp
= time.
GetTimeStep
();
248
ev.
event
= event;
249
{
250
CriticalSection
cs (
m_eventsWithContextMutex
);
251
m_eventsWithContext
.push_back(ev);
252
m_eventsWithContextEmpty
=
false
;
253
}
254
}
255
}
256
257
EventId
258
DefaultSimulatorImpl::ScheduleNow
(
EventImpl
*event)
259
{
260
NS_ASSERT_MSG
(
SystemThread::Equals
(
m_main
),
"Simulator::ScheduleNow Thread-unsafe invocation!"
);
261
262
Scheduler::Event
ev;
263
ev.
impl
= event;
264
ev.
key
.
m_ts
=
m_currentTs
;
265
ev.
key
.
m_context
=
GetContext
();
266
ev.
key
.
m_uid
=
m_uid
;
267
m_uid
++;
268
m_unscheduledEvents
++;
269
m_events
->
Insert
(ev);
270
return
EventId
(event, ev.
key
.
m_ts
, ev.
key
.
m_context
, ev.
key
.
m_uid
);
271
}
272
273
EventId
274
DefaultSimulatorImpl::ScheduleDestroy
(
EventImpl
*event)
275
{
276
NS_ASSERT_MSG
(
SystemThread::Equals
(
m_main
),
"Simulator::ScheduleDestroy Thread-unsafe invocation!"
);
277
278
EventId
id (
Ptr<EventImpl>
(event,
false
),
m_currentTs
, 0xffffffff, 2);
279
m_destroyEvents
.push_back (
id
);
280
m_uid
++;
281
return
id;
282
}
283
284
Time
285
DefaultSimulatorImpl::Now
(
void
)
const
286
{
287
return
TimeStep
(
m_currentTs
);
288
}
289
290
Time
291
DefaultSimulatorImpl::GetDelayLeft
(
const
EventId
&
id
)
const
292
{
293
if
(
IsExpired
(
id
))
294
{
295
return
TimeStep
(0);
296
}
297
else
298
{
299
return
TimeStep
(
id
.GetTs () -
m_currentTs
);
300
}
301
}
302
303
void
304
DefaultSimulatorImpl::Remove
(
const
EventId
&
id
)
305
{
306
if
(
id
.GetUid () == 2)
307
{
308
// destroy events.
309
for
(DestroyEvents::iterator i =
m_destroyEvents
.begin (); i !=
m_destroyEvents
.end (); i++)
310
{
311
if
(*i ==
id
)
312
{
313
m_destroyEvents
.erase (i);
314
break
;
315
}
316
}
317
return
;
318
}
319
if
(
IsExpired
(
id
))
320
{
321
return
;
322
}
323
Scheduler::Event
event;
324
event
.
impl
=
id
.PeekEventImpl ();
325
event
.key.m_ts =
id
.GetTs ();
326
event
.key.m_context =
id
.GetContext ();
327
event
.key.m_uid =
id
.GetUid ();
328
m_events
->
Remove
(event);
329
event
.impl->Cancel ();
330
// whenever we remove an event from the event list, we have to unref it.
331
event
.impl->Unref ();
332
333
m_unscheduledEvents
--;
334
}
335
336
void
337
DefaultSimulatorImpl::Cancel
(
const
EventId
&
id
)
338
{
339
if
(!
IsExpired
(
id
))
340
{
341
id
.PeekEventImpl ()->Cancel ();
342
}
343
}
344
345
bool
346
DefaultSimulatorImpl::IsExpired
(
const
EventId
&ev)
const
347
{
348
if
(ev.
GetUid
() == 2)
349
{
350
if
(ev.
PeekEventImpl
() == 0 ||
351
ev.
PeekEventImpl
()->
IsCancelled
())
352
{
353
return
true
;
354
}
355
// destroy events.
356
for
(DestroyEvents::const_iterator i =
m_destroyEvents
.begin (); i !=
m_destroyEvents
.end (); i++)
357
{
358
if
(*i == ev)
359
{
360
return
false
;
361
}
362
}
363
return
true
;
364
}
365
if
(ev.
PeekEventImpl
() == 0 ||
366
ev.
GetTs
() <
m_currentTs
||
367
(ev.
GetTs
() ==
m_currentTs
&&
368
ev.
GetUid
() <=
m_currentUid
) ||
369
ev.
PeekEventImpl
()->
IsCancelled
())
370
{
371
return
true
;
372
}
373
else
374
{
375
return
false
;
376
}
377
}
378
379
Time
380
DefaultSimulatorImpl::GetMaximumSimulationTime
(
void
)
const
381
{
382
// XXX: I am fairly certain other compilers use other non-standard
383
// post-fixes to indicate 64 bit constants.
384
return
TimeStep
(0x7fffffffffffffffLL);
385
}
386
387
uint32_t
388
DefaultSimulatorImpl::GetContext
(
void
)
const
389
{
390
return
m_currentContext
;
391
}
392
393
}
// namespace ns3
394
395
src
core
model
default-simulator-impl.cc
Generated on Tue Oct 9 2012 16:45:34 for ns-3 by
1.8.1.2