1
2
3
4
5
6
7
8
9
10
11 package nl.tudelft.simulation.dsol.simulators;
12
13 import nl.tudelft.simulation.dsol.formalisms.devs.SimEventInterface;
14 import nl.tudelft.simulation.event.EventType;
15 import nl.tudelft.simulation.logger.Logger;
16
17 /***
18 * The reference implementation of the realTimeClock. The realTime clock is a
19 * DEVDESS simulator which runs at a ratio of realTime. If the executionTime
20 * exceeds the timeStep, a catchup mechanism is triggered to make up lost time
21 * in consecutive steps.
22 * <p>
23 * (c) copyright 2004 <a href="http://www.simulation.tudelft.nl">Delft
24 * University of Technology </a>, the Netherlands. <br>
25 * See for project information <a
26 * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
27 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
28 * License (GPL) </a>, no warranty <br>
29 *
30 * @author <a href="http://www.tbm.tudelft.nl/webstaf/peterja/index.htm">Peter
31 * Jacobs </a>
32 * @version 1.1 Apr 13, 2004
33 * @since 1.4
34 */
35 public class RealTimeClock extends Animator implements
36 DEVDESSSimulatorInterface
37 {
38 /*** the backlog event */
39 public static final EventType BACKLOG_EVENT = new EventType("BACKLOG_EVENT");
40
41 /*** the backLog of the clock */
42 private long backlog = 0L;
43
44 /*** the starttime of the clock */
45 private long startTime = 0L;
46
47 /***
48 * constructs a new RealTimeClock
49 */
50 public RealTimeClock()
51 {
52 super();
53 }
54
55 /***
56 * @see nl.tudelft.simulation.dsol.simulators.DEVSSimulator#run()
57 */
58 public void run()
59 {
60 super.worker.setPriority(Thread.MAX_PRIORITY);
61 this.startTime = System.currentTimeMillis();
62 int count = 0;
63 long animationFactor = Math.round(this.animationDelay / this.timeStep);
64 while (this.isRunning()
65 && !this.eventList.isEmpty()
66 && this.simulatorTime <= this.replication.getRunControl()
67 .getRunLength())
68 {
69 long now = System.currentTimeMillis();
70 double runUntil = (now - this.startTime) + this.timeStep;
71 while (!this.eventList.isEmpty()
72 && this.running
73 && runUntil >= this.eventList.first()
74 .getAbsoluteExecutionTime())
75 {
76 synchronized (super.semaphore)
77 {
78 SimEventInterface event = this.eventList.removeFirst();
79 this.simulatorTime = event.getAbsoluteExecutionTime();
80 try
81 {
82 event.execute();
83 } catch (Exception exception)
84 {
85 Logger.severe(this, "run", exception);
86 }
87 }
88 }
89 if (this.running)
90 {
91 this.simulatorTime = runUntil;
92 }
93 this.fireEvent(SimulatorInterface.TIME_CHANGED_EVENT,
94 this.simulatorTime, this.simulatorTime);
95 if ((count % animationFactor) == 0)
96 {
97 this.fireEvent(AnimatorInterface.UPDATE_ANIMATION_EVENT,
98 this.simulatorTime, this.simulatorTime);
99 }
100 count++;
101 try
102 {
103 long used = System.currentTimeMillis() - now;
104 long delay = Math.round(this.timeStep - used);
105 if (delay >= 0)
106 {
107 long catchUp = Math.min(this.backlog, delay);
108 this.backlog = this.backlog - catchUp;
109 super.fireEvent(BACKLOG_EVENT, (-delay + catchUp));
110 Thread.sleep(delay - catchUp);
111 } else
112 {
113 this.backlog = this.backlog + (-1 * delay);
114 super.fireEvent(BACKLOG_EVENT, -1 * delay);
115 }
116 } catch (InterruptedException interruptedException)
117 {
118
119 interruptedException = null;
120 }
121 }
122 }
123
124 /***
125 * @see nl.tudelft.simulation.dsol.simulators.AnimatorInterface
126 * #getAnimationDelay()
127 */
128 public long getAnimationDelay()
129 {
130 return this.animationDelay;
131 }
132
133 /***
134 * @see nl.tudelft.simulation.dsol.simulators.AnimatorInterface
135 * #setAnimationDelay(long)
136 */
137 public void setAnimationDelay(final long animationDelay)
138 {
139 if (animationDelay < this.timeStep)
140 {
141 Logger
142 .warning(this, "setAnimationDelay",
143 "Be careful: it does not seem wise to have an animationdelay<timeStep");
144 }
145 this.animationDelay = animationDelay;
146 }
147 }