Microscopic Traffic Simulator

- Main Page
- Packages
- Classes
- Files

- File List

Simulation.cs
Go to the documentation of this file.
1 using Microscopic_Traffic_Simulator___Model.Utilities;
2 using System;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Threading;
6
7 namespace Microscopic_Traffic_Simulator___Model.SimulationControl
8 {
12 public class Simulation : IDisposable
13 {
17 private Random random;
18
22 private Timer timer;
23
28 private int validToken = 0;
29
35 private object eventsLock = new object();
36
40 private DateTime dateTimeOfLastAction;
41
45 private TimeSpan currentModelTime;
49 public TimeSpan CurrentModelTime { get { return currentModelTime; } }
50
54 private TimeSpan modelTimeToPause = TimeSpan.MaxValue;
58 public TimeSpan ModelTimeToPause
59 {
60 get { return modelTimeToPause; }
61 set { modelTimeToPause = value; }
62 }
63
67 public event EventHandler ModelTimeChanged;
68
72 public event EventHandler SimulationPaused;
73
77 public event EventHandler SingleSimulationActionPerformed;
78
82 public event EventHandler<SimulationSpeedChangeEventArgs> SimulationSpeedChanged;
83
87 public event EventHandler IsMaxSimulationSpeedChange;
88
92 private SimulationState simulationState = SimulationState.NotRunning;
96 public SimulationState SimulationState { get { return simulationState; } }
97
101 private int usedSeed;
105 public int UsedSeed { get { return usedSeed; } }
106
110 private const double MinimumSimulationSpeed = 0.001;
114 private const double MaximumSimulationSpeed = 10000.0;
118 private double simulationSpeed = 1.0;
122 public double SimulationSpeed
123 {
124 get { return simulationSpeed; }
125 set
126 {
127 if (value < MinimumSimulationSpeed || value > MaximumSimulationSpeed)
128 {
129 return;
130 }
131 double oldSimulationSpeed = simulationSpeed;
132 lock (eventsLock)
133 {
134 if (simulationState == SimulationState.Running)
135 {
136 PauseTimer();
137 }
138 simulationSpeed = value;
139 if (simulationState == SimulationState.Running)
140 {
141 StartOrResumeTimer();
142 }
143 }
144 if (oldSimulationSpeed != simulationSpeed)
145 OnSimulationSpeedChange(oldSimulationSpeed, simulationSpeed);
146 }
147 }
148
152 private bool isMaxSimulationSpeed;
156 public bool IsMaxSimulationSpeed
157 {
158 get { return isMaxSimulationSpeed; }
159 set
160 {
161 if (isMaxSimulationSpeed != value)
162 {
163 isMaxSimulationSpeed = value;
164 if (isMaxSimulationSpeed)
165 {
166 if (simulationState == SimulationState.Running)
167 {
168 lock (eventsLock)
169 {
170 validToken++;
171 }
172 //needed to test the simulation state again because scheduled pause might be performed
173 //just before the locked section right above. Then do not resume timer.
174 if (simulationState == SimulationState.Running)
175 {
176 StartOrResumeTimer();
177 }
178 }
179 }
180 OnIsMaxSimulationSpeedChange();
181 }
182 }
183 }
184
188 private bool IsModelTimeToPauseReached
189 {
190 get
191 {
192 if (simulationActions.Count == 0)
193 return false;
194 else
195 return simulationActions.Top.Key.Time >= modelTimeToPause;
196 }
197 }
198
202 private Heap<SimulationEventGeneratorKey, ISimulationEventsGenerator> simulationActions =
203 new Heap<SimulationEventGeneratorKey, ISimulationEventsGenerator>();
204
208 private List<ISimulationEventsGenerator> simulationActionGenerators =
209 new List<ISimulationEventsGenerator>();
210
216 internal Simulation(List<ISimulationEventsGenerator> simulationEventGenerators)
217 {
218 this.simulationActionGenerators = simulationEventGenerators;
219 }
220
225 private void PushNewActionToCalendarForCurrentActionGenerator(
226 ISimulationEventsGenerator simulationEventsGenerator)
227 {
228 TimeSpan timeToNextAction = simulationEventsGenerator.GetTimeToNextAction(random);
229 if (timeToNextAction != TimeSpan.MaxValue)
230 {
231 simulationActions.Push(new SimulationEventGeneratorKey(currentModelTime + timeToNextAction,
232 simulationEventsGenerator.Priority), simulationEventsGenerator);
233 }
234 }
235
242 private void InitializeSimulationRun(int? seed)
243 {
244 Debug.Assert(simulationActions.Count == 0);
245 Debug.Assert(currentModelTime == TimeSpan.Zero);
246 Debug.Assert(simulationState == SimulationState.NotRunning);
247 foreach (ISimulationEventsGenerator i in simulationActionGenerators)
248 PushNewActionToCalendarForCurrentActionGenerator(i);
249 if (seed == null)
250 usedSeed = (int)(DateTime.Now.Ticks & 0x0000FFFF);
251 else
252 usedSeed = seed.Value;
253 random = new Random(usedSeed);
254 }
255
260 internal void Run(int? seed = null)
261 {
262 Debug.Assert(simulationState == SimulationState.NotRunning ||
263 simulationState == SimulationState.Paused);
264 if (simulationState == SimulationState.NotRunning)
265 {
266 InitializeSimulationRun(seed);
267 }
268 simulationState = SimulationState.Running;
269 ResetModelTimeToPauseIfReached();
270 StartOrResumeTimer();
271 }
272
278 internal void StepForward(int? seed = null)
279 {
280 Debug.Assert(simulationState == SimulationState.NotRunning ||
281 simulationState == SimulationState.Paused);
282 if (simulationState == SimulationState.NotRunning)
283 {
284 InitializeSimulationRun(seed);
285 simulationState = SimulationState.Paused;
286 }
287 ResetModelTimeToPauseIfReached();
288 RunStep();
289 }
290
294 internal void Pause()
295 {
296 lock (eventsLock)
297 {
298 if (simulationState == SimulationState.Paused ||
299 simulationState == SimulationState.NotRunning)
300 {
301 Debug.Assert(true,
302 "Possible simultaneous call of Pause command and scheduled pause or bug in code.");
303 return;
304 }
305 simulationState = SimulationState.Paused;
306 PauseTimer();
307 }
308 }
309
313 internal void Stop()
314 {
315 lock (eventsLock)
316 {
317 if (simulationState == SimulationState.NotRunning)
318 {
319 Debug.Assert(true,
320 "Possible simultaneous call of Stop command and scheduled pause or bug in code.");
321 return;
322 }
323 simulationState = SimulationState.NotRunning;
324 StopTimer();
325 simulationActions.Clear();
326 ResetModelTimeToPause();
327 }
328 }
329
335 private void StartOrResumeTimer()
336 {
337 TimeSpan timeToBeSetInTimer = TimeSpan.Zero;
338 if (!isMaxSimulationSpeed && simulationActions.Count > 0)
339 {
340 dateTimeOfLastAction = DateTime.Now;
341 timeToBeSetInTimer = (simulationActions.Top.Key.Time - currentModelTime).Divide(simulationSpeed);
342 if (timeToBeSetInTimer < TimeSpan.Zero)
343 timeToBeSetInTimer = TimeSpan.Zero;
344 }
345 timer = new Timer(Tick, validToken, timeToBeSetInTimer, Timeout.InfiniteTimeSpan);
346 }
347
353 private ISimulationEventsGenerator GetGeneratorToPerformAnActionAndStoreNewOne()
354 {
355 if (simulationActions.Count == 0)
356 return null;
357 var currentEvent = simulationActions.Pop();
358 currentModelTime = currentEvent.Key.Time;
359 PushNewActionToCalendarForCurrentActionGenerator(currentEvent.Value);
360 return currentEvent.Value;
361 }
362
366 private void RunStep()
367 {
368 new Thread(() =>
369 {
370 lock (eventsLock) //prevent from potential simultaneous executing of Run or Stop command.
371 {
372 var currentActionGenerator = GetGeneratorToPerformAnActionAndStoreNewOne();
373 if (currentActionGenerator == null)
374 return;
375 currentActionGenerator.PerformAction(random);
376 currentModelTime = simulationActions.Top.Key.Time;
377 OnModelTimeChanged();
378 OnSingleSimulationActionPerformed();
379 }
380 }).Start();
381 }
382
389 private void Tick(object state)
390 {
391 lock (eventsLock)
392 {
393 if ((int)state != validToken || simulationActions.Count == 0)
394 {
395 return;
396 }
397 if (IsModelTimeToPauseReached || simulationActions.Top.Value.IsPauseScheduled)
398 {
399 Pause();
400 OnSimulationPaused();
401 return;
402 }
403 var currentActionGenerator = GetGeneratorToPerformAnActionAndStoreNewOne();
404 StartOrResumeTimer();
405 OnModelTimeChanged();
406 currentActionGenerator.PerformAction(random);
407 }
408 }
409
414 private void ResetModelTimeToPauseIfReached()
415 {
416 if (IsModelTimeToPauseReached)
417 {
418 ResetModelTimeToPause();
419 }
420 }
421
425 private void ResetModelTimeToPause()
426 {
427 modelTimeToPause = TimeSpan.MaxValue;
428 }
429
433 private void UpdateTimes()
434 {
435 if ((isMaxSimulationSpeed || IsModelTimeToPauseReached) && simulationActions.Count > 0)
436 currentModelTime = simulationActions.Top.Key.Time;
437 else
438 currentModelTime += (DateTime.Now - dateTimeOfLastAction).Multiply(simulationSpeed);
439 }
440
444 private void PauseTimer()
445 {
446 UpdateTimes();
447 OnModelTimeChanged();
448 validToken++;
449 }
450
454 private void StopTimer()
455 {
456 currentModelTime = TimeSpan.Zero;
457 OnModelTimeChanged();
458 validToken++;
459 }
460
464 private void OnModelTimeChanged()
465 {
466 if (ModelTimeChanged != null)
467 ModelTimeChanged(this, EventArgs.Empty);
468 }
469
474 private void OnSimulationPaused()
475 {
476 if (SimulationPaused != null)
477 SimulationPaused(this, EventArgs.Empty);
478 }
479
483 private void OnSingleSimulationActionPerformed()
484 {
485 if (SingleSimulationActionPerformed != null)
486 SingleSimulationActionPerformed(this, EventArgs.Empty);
487 }
488
494 private void OnSimulationSpeedChange(double oldSimulationSpeed, double newSimulationSpeed)
495 {
496 if (SimulationSpeedChanged != null)
497 {
498 SimulationSpeedChanged(this, new SimulationSpeedChangeEventArgs()
499 {
500 OldSimulationSpeed = oldSimulationSpeed,
501 NewSimulationSpeed = newSimulationSpeed
502 });
503 }
504 }
505
509 private void OnIsMaxSimulationSpeedChange()
510 {
511 if (IsMaxSimulationSpeedChange != null)
512 IsMaxSimulationSpeedChange(this, EventArgs.Empty);
513 }
514
519 protected virtual void Dispose(bool disposing)
520 {
521 if (disposing)
522 {
523 if (timer != null)
524 {
525 timer.Dispose();
526 timer = null;
527 }
528 }
529 }
530
534 public void Dispose()
535 {
536 Dispose(true);
537 GC.SuppressFinalize(this);
538 }
539 }
540 }
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.ModelTimeChanged
EventHandler ModelTimeChanged
An event informing about changing of model time.
Definition: Simulation.cs:67
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.SimulationSpeedChanged
EventHandler< SimulationSpeedChangeEventArgs > SimulationSpeedChanged
Event of simulation speed change.
Definition: Simulation.cs:82
Microscopic_Traffic_Simulator___Model.SimulationControl.ISimulationEventsGenerator.GetTimeToNextAction
TimeSpan GetTimeToNextAction(Random random)
Method for getting time to next action from the implementing class
System
Microscopic_Traffic_Simulator___Model.Utilities
Definition: FileDataStore.cs:3
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.IsMaxSimulationSpeedChange
EventHandler IsMaxSimulationSpeedChange
Event of activation or deactivation of maximum simulation speed.
Definition: Simulation.cs:87
Microscopic_Traffic_Simulator___Model.SimulationControl.SimulationState
SimulationState
Current state of the simulation.
Definition: SimulationState.cs:12
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.SimulationPaused
EventHandler SimulationPaused
An event informing about applying of pause by the simulation control.
Definition: Simulation.cs:72
Microscopic_Traffic_Simulator___Model.SimulationControl.ISimulationEventsGenerator.Priority
int Priority
Priority determining the rank of the events which have the same time.
Definition: ISimulationEventsGenerator.cs:33
Microscopic_Traffic_Simulator___Model.SimulationControl.SimulationSpeedChangeEventArgs
Event args containing old and new simulation speed.
Definition: SimulationSpeedChangeEventArgs.cs:8
Microscopic_Traffic_Simulator___Model.Utilities.Heap
Heap data structure where values of items are ordered by their keys.
Definition: Heap.cs:11
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.Dispose
void Dispose()
Disposes cellular topology resources.
Definition: Simulation.cs:534
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.SingleSimulationActionPerformed
EventHandler SingleSimulationActionPerformed
An event informing about finishing of simulation action.
Definition: Simulation.cs:77
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation
Class controlling performing simulation actions by simulation calendar.
Definition: Simulation.cs:12
Microscopic_Traffic_Simulator___Model.SimulationControl.ISimulationEventsGenerator
Every class which performs some repeating action should implement this interface
Definition: ISimulationEventsGenerator.cs:8
Microscopic_Traffic_Simulator___Model
Microscopic_Traffic_Simulator___Model.SimulationControl.Simulation.Dispose
virtual void Dispose(bool disposing)
Dispose disposable fields.
Definition: Simulation.cs:519