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