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
realtime-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) 2008 University of Washington
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
19
#include "
simulator.h
"
20
#include "
realtime-simulator-impl.h
"
21
#include "
wall-clock-synchronizer.h
"
22
#include "
scheduler.h
"
23
#include "
event-impl.h
"
24
#include "
synchronizer.h
"
25
26
#include "
ptr.h
"
27
#include "
pointer.h
"
28
#include "
assert.h
"
29
#include "
fatal-error.h
"
30
#include "
log.h
"
31
#include "
system-mutex.h
"
32
#include "
boolean.h
"
33
#include "
enum.h
"
34
35
36
#include <cmath>
37
38
// Note: Logging in this file is largely avoided due to the
39
// number of calls that are made to these functions and the possibility
40
// of causing recursions leading to stack overflow
41
42
NS_LOG_COMPONENT_DEFINE
(
"RealtimeSimulatorImpl"
);
43
44
namespace
ns3 {
45
46
NS_OBJECT_ENSURE_REGISTERED
(RealtimeSimulatorImpl);
47
48
TypeId
49
RealtimeSimulatorImpl::GetTypeId
(
void
)
50
{
51
static
TypeId
tid =
TypeId
(
"ns3::RealtimeSimulatorImpl"
)
52
.
SetParent
<
SimulatorImpl
> ()
53
.AddConstructor<RealtimeSimulatorImpl> ()
54
.AddAttribute (
"SynchronizationMode"
,
55
"What to do if the simulation cannot keep up with real time."
,
56
EnumValue
(
SYNC_BEST_EFFORT
),
57
MakeEnumAccessor
(&
RealtimeSimulatorImpl::SetSynchronizationMode
),
58
MakeEnumChecker
(
SYNC_BEST_EFFORT
,
"BestEffort"
,
59
SYNC_HARD_LIMIT
,
"HardLimit"
))
60
.AddAttribute (
"HardLimit"
,
61
"Maximum acceptable real-time jitter (used in conjunction with SynchronizationMode=HardLimit)"
,
62
TimeValue
(
Seconds
(0.1)),
63
MakeTimeAccessor (&
RealtimeSimulatorImpl::m_hardLimit
),
64
MakeTimeChecker ())
65
;
66
return
tid;
67
}
68
69
70
RealtimeSimulatorImpl::RealtimeSimulatorImpl
()
71
{
72
NS_LOG_FUNCTION
(
this
);
73
74
m_stop
=
false
;
75
m_running
=
false
;
76
// uids are allocated from 4.
77
// uid 0 is "invalid" events
78
// uid 1 is "now" events
79
// uid 2 is "destroy" events
80
m_uid
= 4;
81
// before ::Run is entered, the m_currentUid will be zero
82
m_currentUid
= 0;
83
m_currentTs
= 0;
84
m_currentContext
= 0xffffffff;
85
m_unscheduledEvents
= 0;
86
87
m_main
=
SystemThread::Self
();
88
89
// Be very careful not to do anything that would cause a change or assignment
90
// of the underlying reference counts of m_synchronizer or you will be sorry.
91
m_synchronizer
= CreateObject<WallClockSynchronizer> ();
92
}
93
94
RealtimeSimulatorImpl::~RealtimeSimulatorImpl
()
95
{
96
NS_LOG_FUNCTION
(
this
);
97
}
98
99
void
100
RealtimeSimulatorImpl::DoDispose
(
void
)
101
{
102
NS_LOG_FUNCTION
(
this
);
103
while
(!
m_events
->
IsEmpty
())
104
{
105
Scheduler::Event
next =
m_events
->
RemoveNext
();
106
next.
impl
->
Unref
();
107
}
108
m_events
= 0;
109
m_synchronizer
= 0;
110
SimulatorImpl::DoDispose
();
111
}
112
113
void
114
RealtimeSimulatorImpl::Destroy
()
115
{
116
NS_LOG_FUNCTION
(
this
);
117
118
//
119
// This function is only called with the private version "disconnected" from
120
// the main simulator functions. We rely on the user not calling
121
// Simulator::Destroy while there is a chance that a worker thread could be
122
// accessing the current instance of the private object. In practice this
123
// means shutting down the workers and doing a Join() before calling the
124
// Simulator::Destroy().
125
//
126
while
(
m_destroyEvents
.empty () ==
false
)
127
{
128
Ptr<EventImpl>
ev =
m_destroyEvents
.front ().PeekEventImpl ();
129
m_destroyEvents
.pop_front ();
130
NS_LOG_LOGIC
(
"handle destroy "
<< ev);
131
if
(ev->
IsCancelled
() ==
false
)
132
{
133
ev->
Invoke
();
134
}
135
}
136
}
137
138
void
139
RealtimeSimulatorImpl::SetScheduler
(
ObjectFactory
schedulerFactory)
140
{
141
NS_LOG_FUNCTION
(
this
<< schedulerFactory);
142
143
Ptr<Scheduler>
scheduler = schedulerFactory.
Create
<
Scheduler
> ();
144
145
{
146
CriticalSection
cs (
m_mutex
);
147
148
if
(
m_events
!= 0)
149
{
150
while
(
m_events
->
IsEmpty
() ==
false
)
151
{
152
Scheduler::Event
next =
m_events
->
RemoveNext
();
153
scheduler->
Insert
(next);
154
}
155
}
156
m_events
= scheduler;
157
}
158
}
159
160
void
161
RealtimeSimulatorImpl::ProcessOneEvent
(
void
)
162
{
163
//
164
// The idea here is to wait until the next event comes due. In the case of
165
// a realtime simulation, we want real time to be consumed between events.
166
// It is the realtime synchronizer that causes real time to be consumed by
167
// doing some kind of a wait.
168
//
169
// We need to be able to have external events (such as a packet reception event)
170
// cause us to re-evaluate our state. The way this works is that the synchronizer
171
// gets interrupted and returns. So, there is a possibility that things may change
172
// out from under us dynamically. In this case, we need to re-evaluate how long to
173
// wait in a for-loop until we have waited sucessfully (until a timeout) for the
174
// event at the head of the event list.
175
//
176
// m_synchronizer->Synchronize will return true if the wait was completed without
177
// interruption, otherwise it will return false indicating that something has changed
178
// out from under us. If we sit in the for-loop trying to synchronize until
179
// Synchronize() returns true, we will have successfully synchronized the execution
180
// time of the next event with the wall clock time of the synchronizer.
181
//
182
183
for
(;;)
184
{
185
uint64_t tsDelay = 0;
186
uint64_t tsNext = 0;
187
188
//
189
// It is important to understand that m_currentTs is interpreted only as the
190
// timestamp of the last event we executed. Current time can a bit of a
191
// slippery concept in realtime mode. What we have here is a discrete event
192
// simulator, so the last event is, by defintion, executed entirely at a single
193
// discrete time. This is the definition of m_currentTs. It really has
194
// nothing to do with the current real time, except that we are trying to arrange
195
// that at the instant of the beginning of event execution, the current real time
196
// and m_currentTs coincide.
197
//
198
// We use tsNow as the indication of the current real time.
199
//
200
uint64_t tsNow;
201
202
{
203
CriticalSection
cs (
m_mutex
);
204
//
205
// Since we are in realtime mode, the time to delay has got to be the
206
// difference between the current realtime and the timestamp of the next
207
// event. Since m_currentTs is actually the timestamp of the last event we
208
// executed, it's not particularly meaningful for us here since real time has
209
// certainly elapsed since it was last updated.
210
//
211
// It is possible that the current realtime has drifted past the next event
212
// time so we need to be careful about that and not delay in that case.
213
//
214
NS_ASSERT_MSG
(
m_synchronizer
->
Realtime
(),
215
"RealtimeSimulatorImpl::ProcessOneEvent (): Synchronizer reports not Realtime ()"
);
216
217
//
218
// tsNow is set to the normalized current real time. When the simulation was
219
// started, the current real time was effectively set to zero; so tsNow is
220
// the current "real" simulation time.
221
//
222
// tsNext is the simulation time of the next event we want to execute.
223
//
224
tsNow =
m_synchronizer
->
GetCurrentRealtime
();
225
tsNext =
NextTs
();
226
227
//
228
// tsDelay is therefore the real time we need to delay in order to bring the
229
// real time in sync with the simulation time. If we wait for this amount of
230
// real time, we will accomplish moving the simulation time at the same rate
231
// as the real time. This is typically called "pacing" the simulation time.
232
//
233
// We do have to be careful if we are falling behind. If so, tsDelay must be
234
// zero. If we're late, don't dawdle.
235
//
236
if
(tsNext <= tsNow)
237
{
238
tsDelay = 0;
239
}
240
else
241
{
242
tsDelay = tsNext - tsNow;
243
}
244
245
//
246
// We've figured out how long we need to delay in order to pace the
247
// simulation time with the real time. We're going to sleep, but need
248
// to work with the synchronizer to make sure we're awakened if something
249
// external happens (like a packet is received). This next line resets
250
// the synchronizer so that any future event will cause it to interrupt.
251
//
252
m_synchronizer
->
SetCondition
(
false
);
253
}
254
255
//
256
// We have a time to delay. This time may actually not be valid anymore
257
// since we released the critical section immediately above, and a real-time
258
// ScheduleReal or ScheduleRealNow may have snuck in, well, between the
259
// closing brace above and this comment so to speak. If this is the case,
260
// that schedule operation will have done a synchronizer Signal() that
261
// will set the condition variable to true and cause the Synchronize call
262
// below to return immediately.
263
//
264
// It's easiest to understand if you just consider a short tsDelay that only
265
// requires a SpinWait down in the synchronizer. What will happen is that
266
// whan Synchronize calls SpinWait, SpinWait will look directly at its
267
// condition variable. Note that we set this condition variable to false
268
// inside the critical section above.
269
//
270
// SpinWait will go into a forever loop until either the time has expired or
271
// until the condition variable becomes true. A true condition indicates that
272
// the wait should stop. The condition is set to true by one of the Schedule
273
// methods of the simulator; so if we are in a wait down in Synchronize, and
274
// a Simulator::ScheduleReal is done, the wait down in Synchronize will exit and
275
// Synchronize will return false. This means we have not actually synchronized
276
// to the event expiration time. If no real-time schedule operation is done
277
// while down in Synchronize, the wait will time out and Synchronize will return
278
// true. This indicates that we have synchronized to the event time.
279
//
280
// So we need to stay in this for loop, looking for the next event timestamp and
281
// attempting to sleep until its due. If we've slept until the timestamp is due,
282
// Synchronize returns true and we break out of the sync loop. If an external
283
// event happens that requires a re-schedule, Synchronize returns false and
284
// we re-evaluate our timing by continuing in the loop.
285
//
286
// It is expected that tsDelay become shorter as external events interrupt our
287
// waits.
288
//
289
if
(
m_synchronizer
->
Synchronize
(tsNow, tsDelay))
290
{
291
NS_LOG_LOGIC
(
"Interrupted ..."
);
292
break
;
293
}
294
295
//
296
// If we get to this point, we have been interrupted during a wait by a real-time
297
// schedule operation. This means all bets are off regarding tsDelay and we need
298
// to re-evaluate what it is we want to do. We'll loop back around in the
299
// for-loop and start again from scratch.
300
//
301
}
302
303
//
304
// If we break out of the for-loop above, we have waited until the time specified
305
// by the event that was at the head of the event list when we started the process.
306
// Since there is a bunch of code that was executed outside a critical section (the
307
// Synchronize call) we cannot be sure that the event at the head of the event list
308
// is the one we think it is. What we can be sure of is that it is time to execute
309
// whatever event is at the head of this list if the list is in time order.
310
//
311
Scheduler::Event
next;
312
313
{
314
CriticalSection
cs (
m_mutex
);
315
316
//
317
// We do know we're waiting for an event, so there had better be an event on the
318
// event queue. Let's pull it off. When we release the critical section, the
319
// event we're working on won't be on the list and so subsequent operations won't
320
// mess with us.
321
//
322
NS_ASSERT_MSG
(
m_events
->
IsEmpty
() ==
false
,
323
"RealtimeSimulatorImpl::ProcessOneEvent(): event queue is empty"
);
324
next =
m_events
->
RemoveNext
();
325
m_unscheduledEvents
--;
326
327
//
328
// We cannot make any assumption that "next" is the same event we originally waited
329
// for. We can only assume that only that it must be due and cannot cause time
330
// to move backward.
331
//
332
NS_ASSERT_MSG
(next.key.m_ts >=
m_currentTs
,
333
"RealtimeSimulatorImpl::ProcessOneEvent(): "
334
"next.GetTs() earlier than m_currentTs (list order error)"
);
335
NS_LOG_LOGIC
(
"handle "
<< next.key.m_ts);
336
337
//
338
// Update the current simulation time to be the timestamp of the event we're
339
// executing. From the rest of the simulation's point of view, simulation time
340
// is frozen until the next event is executed.
341
//
342
m_currentTs
= next.key.m_ts;
343
m_currentContext
= next.key.m_context;
344
m_currentUid
= next.key.m_uid;
345
346
//
347
// We're about to run the event and we've done our best to synchronize this
348
// event execution time to real time. Now, if we're in SYNC_HARD_LIMIT mode
349
// we have to decide if we've done a good enough job and if we haven't, we've
350
// been asked to commit ritual suicide.
351
//
352
// We check the simulation time against the current real time to make this
353
// judgement.
354
//
355
if
(
m_synchronizationMode
==
SYNC_HARD_LIMIT
)
356
{
357
uint64_t tsFinal =
m_synchronizer
->
GetCurrentRealtime
();
358
uint64_t tsJitter;
359
360
if
(tsFinal >=
m_currentTs
)
361
{
362
tsJitter = tsFinal -
m_currentTs
;
363
}
364
else
365
{
366
tsJitter =
m_currentTs
- tsFinal;
367
}
368
369
if
(tsJitter > static_cast<uint64_t>(
m_hardLimit
.
GetTimeStep
()))
370
{
371
NS_FATAL_ERROR
(
"RealtimeSimulatorImpl::ProcessOneEvent (): "
372
"Hard real-time limit exceeded (jitter = "
<< tsJitter <<
")"
);
373
}
374
}
375
}
376
377
//
378
// We have got the event we're about to execute completely disentangled from the
379
// event list so we can execute it outside a critical section without fear of someone
380
// changing things out from under us.
381
382
EventImpl
*
event
= next.
impl
;
383
m_synchronizer
->
EventStart
();
384
event
->Invoke ();
385
m_synchronizer
->
EventEnd
();
386
event
->Unref ();
387
}
388
389
bool
390
RealtimeSimulatorImpl::IsFinished
(
void
)
const
391
{
392
bool
rc;
393
{
394
CriticalSection
cs (
m_mutex
);
395
rc =
m_events
->
IsEmpty
() ||
m_stop
;
396
}
397
398
return
rc;
399
}
400
401
//
402
// Peeks into event list. Should be called with critical section locked.
403
//
404
uint64_t
405
RealtimeSimulatorImpl::NextTs
(
void
)
const
406
{
407
NS_ASSERT_MSG
(
m_events
->
IsEmpty
() ==
false
,
408
"RealtimeSimulatorImpl::NextTs(): event queue is empty"
);
409
Scheduler::Event
ev =
m_events
->
PeekNext
();
410
return
ev.
key
.
m_ts
;
411
}
412
413
void
414
RealtimeSimulatorImpl::Run
(
void
)
415
{
416
NS_LOG_FUNCTION
(
this
);
417
418
NS_ASSERT_MSG
(
m_running
==
false
,
419
"RealtimeSimulatorImpl::Run(): Simulator already running"
);
420
421
// Set the current threadId as the main threadId
422
m_main
=
SystemThread::Self
();
423
424
m_stop
=
false
;
425
m_running
=
true
;
426
m_synchronizer
->
SetOrigin
(
m_currentTs
);
427
428
// Sleep until signalled
429
uint64_t tsNow;
430
uint64_t tsDelay = 1000000000;
// wait time of 1 second (in nanoseconds)
431
432
while
(!
m_stop
)
433
{
434
bool
process =
false
;
435
{
436
CriticalSection
cs (
m_mutex
);
437
438
if
(!
m_events
->
IsEmpty
())
439
{
440
process =
true
;
441
}
442
else
443
{
444
// Get current timestamp while holding the critical section
445
tsNow =
m_synchronizer
->
GetCurrentRealtime
();
446
}
447
}
448
449
if
(!process)
450
{
451
// Sleep until signalled
452
tsNow =
m_synchronizer
->
Synchronize
(tsNow, tsDelay);
453
454
// Re-check event queue
455
continue
;
456
}
457
458
ProcessOneEvent
();
459
}
460
461
//
462
// If the simulator stopped naturally by lack of events, make a
463
// consistency test to check that we didn't lose any events along the way.
464
//
465
{
466
CriticalSection
cs (
m_mutex
);
467
468
NS_ASSERT_MSG
(
m_events
->
IsEmpty
() ==
false
||
m_unscheduledEvents
== 0,
469
"RealtimeSimulatorImpl::Run(): Empty queue and unprocessed events"
);
470
}
471
472
m_running
=
false
;
473
}
474
475
bool
476
RealtimeSimulatorImpl::Running
(
void
)
const
477
{
478
return
m_running
;
479
}
480
481
bool
482
RealtimeSimulatorImpl::Realtime
(
void
)
const
483
{
484
return
m_synchronizer
->
Realtime
();
485
}
486
487
void
488
RealtimeSimulatorImpl::Stop
(
void
)
489
{
490
NS_LOG_FUNCTION
(
this
);
491
m_stop
=
true
;
492
}
493
494
void
495
RealtimeSimulatorImpl::Stop
(
Time
const
&time)
496
{
497
NS_LOG_FUNCTION
(
this
<< time);
498
Simulator::Schedule
(time, &
Simulator::Stop
);
499
}
500
501
//
502
// Schedule an event for a _relative_ time in the future.
503
//
504
EventId
505
RealtimeSimulatorImpl::Schedule
(
Time
const
&time,
EventImpl
*impl)
506
{
507
NS_LOG_FUNCTION
(
this
<< time << impl);
508
509
Scheduler::Event
ev;
510
{
511
CriticalSection
cs (
m_mutex
);
512
//
513
// This is the reason we had to bring the absolute time calcualtion in from the
514
// simulator.h into the implementation. Since the implementations may be
515
// multi-threaded, we need this calculation to be atomic. You can see it is
516
// here since we are running in a CriticalSection.
517
//
518
Time
tAbsolute =
Simulator::Now
() + time;
519
NS_ASSERT_MSG
(tAbsolute.
IsPositive
(),
"RealtimeSimulatorImpl::Schedule(): Negative time"
);
520
NS_ASSERT_MSG
(tAbsolute >=
TimeStep
(
m_currentTs
),
"RealtimeSimulatorImpl::Schedule(): time < m_currentTs"
);
521
ev.
impl
= impl;
522
ev.
key
.
m_ts
= (uint64_t) tAbsolute.
GetTimeStep
();
523
ev.
key
.
m_context
=
GetContext
();
524
ev.
key
.
m_uid
=
m_uid
;
525
m_uid
++;
526
m_unscheduledEvents
++;
527
m_events
->
Insert
(ev);
528
m_synchronizer
->
Signal
();
529
}
530
531
return
EventId
(impl, ev.
key
.
m_ts
, ev.
key
.
m_context
, ev.
key
.
m_uid
);
532
}
533
534
void
535
RealtimeSimulatorImpl::ScheduleWithContext
(uint32_t context,
Time
const
&time,
EventImpl
*impl)
536
{
537
NS_LOG_FUNCTION
(
this
<< context << time << impl);
538
539
{
540
CriticalSection
cs (
m_mutex
);
541
uint64_t ts;
542
543
if
(
SystemThread::Equals
(
m_main
))
544
{
545
ts =
m_currentTs
+ time.
GetTimeStep
();
546
}
547
else
548
{
549
//
550
// If the simulator is running, we're pacing and have a meaningful
551
// realtime clock. If we're not, then m_currentTs is where we stopped.
552
//
553
ts =
m_running
?
m_synchronizer
->
GetCurrentRealtime
() :
m_currentTs
;
554
ts += time.
GetTimeStep
();
555
}
556
557
NS_ASSERT_MSG
(ts >=
m_currentTs
,
"RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs"
);
558
Scheduler::Event
ev;
559
ev.
impl
= impl;
560
ev.
key
.
m_ts
= ts;
561
ev.
key
.
m_context
= context;
562
ev.
key
.
m_uid
=
m_uid
;
563
m_uid
++;
564
m_unscheduledEvents
++;
565
m_events
->
Insert
(ev);
566
m_synchronizer
->
Signal
();
567
}
568
}
569
570
EventId
571
RealtimeSimulatorImpl::ScheduleNow
(
EventImpl
*impl)
572
{
573
NS_LOG_FUNCTION
(
this
<< impl);
574
Scheduler::Event
ev;
575
{
576
CriticalSection
cs (
m_mutex
);
577
578
ev.
impl
= impl;
579
ev.
key
.
m_ts
=
m_currentTs
;
580
ev.
key
.
m_context
=
GetContext
();
581
ev.
key
.
m_uid
=
m_uid
;
582
m_uid
++;
583
m_unscheduledEvents
++;
584
m_events
->
Insert
(ev);
585
m_synchronizer
->
Signal
();
586
}
587
588
return
EventId
(impl, ev.
key
.
m_ts
, ev.
key
.
m_context
, ev.
key
.
m_uid
);
589
}
590
591
Time
592
RealtimeSimulatorImpl::Now
(
void
)
const
593
{
594
return
TimeStep
(
m_currentTs
);
595
}
596
597
//
598
// Schedule an event for a _relative_ time in the future.
599
//
600
void
601
RealtimeSimulatorImpl::ScheduleRealtimeWithContext
(uint32_t context,
Time
const
&time,
EventImpl
*impl)
602
{
603
NS_LOG_FUNCTION
(
this
<< context << time << impl);
604
605
{
606
CriticalSection
cs (
m_mutex
);
607
608
uint64_t ts =
m_synchronizer
->
GetCurrentRealtime
() + time.
GetTimeStep
();
609
NS_ASSERT_MSG
(ts >=
m_currentTs
,
"RealtimeSimulatorImpl::ScheduleRealtime(): schedule for time < m_currentTs"
);
610
Scheduler::Event
ev;
611
ev.
impl
= impl;
612
ev.
key
.
m_ts
= ts;
613
ev.
key
.
m_uid
=
m_uid
;
614
m_uid
++;
615
m_unscheduledEvents
++;
616
m_events
->
Insert
(ev);
617
m_synchronizer
->
Signal
();
618
}
619
}
620
621
void
622
RealtimeSimulatorImpl::ScheduleRealtime
(
Time
const
&time,
EventImpl
*impl)
623
{
624
NS_LOG_FUNCTION
(
this
<< time << impl);
625
ScheduleRealtimeWithContext
(
GetContext
(), time, impl);
626
}
627
628
void
629
RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext
(uint32_t context,
EventImpl
*impl)
630
{
631
NS_LOG_FUNCTION
(
this
<< context << impl);
632
{
633
CriticalSection
cs (
m_mutex
);
634
635
//
636
// If the simulator is running, we're pacing and have a meaningful
637
// realtime clock. If we're not, then m_currentTs is were we stopped.
638
//
639
uint64_t ts =
m_running
?
m_synchronizer
->
GetCurrentRealtime
() :
m_currentTs
;
640
NS_ASSERT_MSG
(ts >=
m_currentTs
,
641
"RealtimeSimulatorImpl::ScheduleRealtimeNowWithContext(): schedule for time < m_currentTs"
);
642
Scheduler::Event
ev;
643
ev.
impl
= impl;
644
ev.
key
.
m_ts
= ts;
645
ev.
key
.
m_uid
=
m_uid
;
646
ev.
key
.
m_context
= context;
647
m_uid
++;
648
m_unscheduledEvents
++;
649
m_events
->
Insert
(ev);
650
m_synchronizer
->
Signal
();
651
}
652
}
653
654
void
655
RealtimeSimulatorImpl::ScheduleRealtimeNow
(
EventImpl
*impl)
656
{
657
NS_LOG_FUNCTION
(
this
<< impl);
658
ScheduleRealtimeNowWithContext
(
GetContext
(), impl);
659
}
660
661
Time
662
RealtimeSimulatorImpl::RealtimeNow
(
void
)
const
663
{
664
return
TimeStep
(
m_synchronizer
->
GetCurrentRealtime
());
665
}
666
667
EventId
668
RealtimeSimulatorImpl::ScheduleDestroy
(
EventImpl
*impl)
669
{
670
NS_LOG_FUNCTION
(
this
<< impl);
671
672
EventId
id;
673
{
674
CriticalSection
cs (
m_mutex
);
675
676
//
677
// Time doesn't really matter here (especially in realtime mode). It is
678
// overridden by the uid of 2 which identifies this as an event to be
679
// executed at Simulator::Destroy time.
680
//
681
id
=
EventId
(
Ptr<EventImpl>
(impl,
false
),
m_currentTs
, 0xffffffff, 2);
682
m_destroyEvents
.push_back (
id
);
683
m_uid
++;
684
}
685
686
return
id;
687
}
688
689
Time
690
RealtimeSimulatorImpl::GetDelayLeft
(
const
EventId
&
id
)
const
691
{
692
//
693
// If the event has expired, there is no delay until it runs. It is not the
694
// case that there is a negative time until it runs.
695
//
696
if
(
IsExpired
(
id
))
697
{
698
return
TimeStep
(0);
699
}
700
701
return
TimeStep
(
id
.GetTs () -
m_currentTs
);
702
}
703
704
void
705
RealtimeSimulatorImpl::Remove
(
const
EventId
&
id
)
706
{
707
if
(
id
.GetUid () == 2)
708
{
709
// destroy events.
710
for
(DestroyEvents::iterator i =
m_destroyEvents
.begin ();
711
i !=
m_destroyEvents
.end ();
712
i++)
713
{
714
if
(*i ==
id
)
715
{
716
m_destroyEvents
.erase (i);
717
break
;
718
}
719
}
720
return
;
721
}
722
if
(
IsExpired
(
id
))
723
{
724
return
;
725
}
726
727
{
728
CriticalSection
cs (
m_mutex
);
729
730
Scheduler::Event
event;
731
event
.
impl
=
id
.PeekEventImpl ();
732
event
.key.m_ts =
id
.GetTs ();
733
event
.key.m_context =
id
.GetContext ();
734
event
.key.m_uid =
id
.GetUid ();
735
736
m_events
->
Remove
(event);
737
m_unscheduledEvents
--;
738
event
.impl->Cancel ();
739
event
.impl->Unref ();
740
}
741
}
742
743
void
744
RealtimeSimulatorImpl::Cancel
(
const
EventId
&
id
)
745
{
746
if
(
IsExpired
(
id
) ==
false
)
747
{
748
id
.PeekEventImpl ()->Cancel ();
749
}
750
}
751
752
bool
753
RealtimeSimulatorImpl::IsExpired
(
const
EventId
&ev)
const
754
{
755
if
(ev.
GetUid
() == 2)
756
{
757
if
(ev.
PeekEventImpl
() == 0 ||
758
ev.
PeekEventImpl
()->
IsCancelled
())
759
{
760
return
true
;
761
}
762
// destroy events.
763
for
(DestroyEvents::const_iterator i =
m_destroyEvents
.begin ();
764
i !=
m_destroyEvents
.end (); i++)
765
{
766
if
(*i == ev)
767
{
768
return
false
;
769
}
770
}
771
return
true
;
772
}
773
774
//
775
// If the time of the event is less than the current timestamp of the
776
// simulator, the simulator has gone past the invocation time of the
777
// event, so the statement ev.GetTs () < m_currentTs does mean that
778
// the event has been fired even in realtime mode.
779
//
780
// The same is true for the next line involving the m_currentUid.
781
//
782
if
(ev.
PeekEventImpl
() == 0 ||
783
ev.
GetTs
() <
m_currentTs
||
784
(ev.
GetTs
() ==
m_currentTs
&& ev.
GetUid
() <=
m_currentUid
) ||
785
ev.
PeekEventImpl
()->
IsCancelled
())
786
{
787
return
true
;
788
}
789
else
790
{
791
return
false
;
792
}
793
}
794
795
Time
796
RealtimeSimulatorImpl::GetMaximumSimulationTime
(
void
)
const
797
{
798
// XXX: I am fairly certain other compilers use other non-standard
799
// post-fixes to indicate 64 bit constants.
800
return
TimeStep
(0x7fffffffffffffffLL);
801
}
802
803
// System ID for non-distributed simulation is always zero
804
uint32_t
805
RealtimeSimulatorImpl::GetSystemId
(
void
)
const
806
{
807
return
0;
808
}
809
810
uint32_t
811
RealtimeSimulatorImpl::GetContext
(
void
)
const
812
{
813
return
m_currentContext
;
814
}
815
816
void
817
RealtimeSimulatorImpl::SetSynchronizationMode
(
enum
SynchronizationMode
mode)
818
{
819
NS_LOG_FUNCTION
(
this
<< mode);
820
m_synchronizationMode
= mode;
821
}
822
823
RealtimeSimulatorImpl::SynchronizationMode
824
RealtimeSimulatorImpl::GetSynchronizationMode
(
void
)
const
825
{
826
NS_LOG_FUNCTION
(
this
);
827
return
m_synchronizationMode
;
828
}
829
830
void
831
RealtimeSimulatorImpl::SetHardLimit
(
Time
limit)
832
{
833
NS_LOG_FUNCTION
(
this
<< limit);
834
m_hardLimit
= limit;
835
}
836
837
Time
838
RealtimeSimulatorImpl::GetHardLimit
(
void
)
const
839
{
840
NS_LOG_FUNCTION
(
this
);
841
return
m_hardLimit
;
842
}
843
844
}
// namespace ns3
src
core
model
realtime-simulator-impl.cc
Generated on Tue May 14 2013 11:08:18 for ns-3 by
1.8.1.2