1
2
3
4
5
6
7
8
9
10 package nl.tudelft.simulation.dsol.simulators;
11
12 import java.rmi.RemoteException;
13
14 import nl.tudelft.simulation.dsol.SimRuntimeException;
15 import nl.tudelft.simulation.dsol.experiment.Replication;
16 import nl.tudelft.simulation.event.Event;
17 import nl.tudelft.simulation.event.EventProducer;
18 import nl.tudelft.simulation.jstats.statistics.StatisticsObject;
19 import nl.tudelft.simulation.language.concurrent.WorkerThread;
20 import nl.tudelft.simulation.logger.Logger;
21
22 /***
23 * The Simulator class is an abstract implementation of the SimulatorInterface.
24 * <p>
25 * (c) copyright 2003 <a href="http://www.simulation.tudelft.nl">Delft
26 * University of Technology </a>, the Netherlands. <br>
27 * See for project information <a href="http://www.simulation.tudelft.nl">
28 * www.simulation.tudelft.nl </a> <br>
29 * License of use: <a href="http://www.gnu.org/copyleft/gpl.html">General Public
30 * License (GPL) </a>, no warranty <br>
31 *
32 * @author <a href="http://www.simulation.tudelft.nl/people/jacobs.html">Peter
33 * Jacobs </a>
34 * @version 1.13 2004-03-18
35 * @since 1.0
36 */
37 public abstract class Simulator extends EventProducer implements
38 SimulatorInterface, Runnable
39 {
40
41 /***
42 * simulatorTime represents the simulationTime
43 *
44 * @uml.property name="simulatorTime"
45 */
46 protected double simulatorTime = Double.NaN;
47
48 /***
49 * running represents the binary state of the simulator
50 *
51 * @uml.property name="running"
52 */
53 protected boolean running = false;
54
55 /***
56 * replication represents the currently active replication
57 *
58 * @uml.property name="replication"
59 */
60 protected Replication replication = null;
61
62
63 /*** a worker */
64 protected WorkerThread worker = null;
65
66 /*** the simulatorSemaphore */
67 protected Object semaphore = new Object();
68
69 /***
70 * constructs a new Simulator
71 */
72 public Simulator()
73 {
74 this.worker = new WorkerThread(this.getClass().getName(), this);
75 }
76
77 /***
78 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface
79 * #getSimulatorTime()
80 *
81 * @uml.property name="simulatorTime"
82 */
83 public double getSimulatorTime()
84 {
85 return this.simulatorTime;
86 }
87
88 /***
89 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface
90 * #getReplication()
91 *
92 * @uml.property name="replication"
93 */
94 public Replication getReplication()
95 {
96 return this.replication;
97 }
98
99
100 /***
101 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface
102 * #initialize(Replication)
103 */
104 public void initialize(final Replication replication)
105 throws RemoteException, SimRuntimeException
106 {
107 if (replication == null)
108 {
109 throw new IllegalArgumentException("replication == null ?");
110 }
111 if (this.isRunning())
112 {
113 throw new SimRuntimeException(
114 "Cannot initialize a running simulator");
115 }
116 synchronized (this.semaphore)
117 {
118 this.removeAllListeners(StatisticsObject.class);
119 this.replication = replication;
120 this.simulatorTime = 0.0;
121 this.fireEvent(SimulatorInterface.START_REPLICATION_EVENT, null,
122 ((SimulatorInterface) this).getSimulatorTime());
123 this.fireEvent(SimulatorInterface.TIME_CHANGED_EVENT,
124 this.simulatorTime, this.simulatorTime);
125 Logger.finer(this, "initialize", "OK");
126 }
127 }
128
129 /***
130 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface#isRunning()
131 *
132 * @uml.property name="running"
133 */
134 public boolean isRunning()
135 {
136 return this.running;
137 }
138
139 /***
140 * The run method defines the actual time step mechanism of the simulator.
141 * The implementation of this method depends on the formalism. Where
142 * discrete event formalisms loop over an eventlist continuous simulators
143 * take pre-defined time steps.
144 *
145 */
146 public abstract void run();
147
148 /***
149 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface#start()
150 */
151 public void start() throws SimRuntimeException, RemoteException
152 {
153 if (this.isRunning())
154 {
155 throw new SimRuntimeException("Cannot start a running simulator");
156 }
157 if (this.replication == null)
158 {
159 throw new SimRuntimeException("Cannot start a simulator"
160 + " without replication details");
161 }
162 if (this.simulatorTime >= this.replication.getRunControl()
163 .getRunLength())
164 {
165 throw new SimRuntimeException("Cannot start simulator : "
166 + "simulatorTime = runLength");
167 }
168 synchronized (this.semaphore)
169 {
170 this.running = true;
171 this.fireEvent(START_EVENT, null);
172 this.fireEvent(SimulatorInterface.TIME_CHANGED_EVENT,
173 this.simulatorTime, this.simulatorTime);
174 Logger.finer(this, "start", "OK");
175 if (!Thread.currentThread().getName().equals(this.worker.getName()))
176 {
177 this.worker.interrupt();
178 } else
179 {
180 this.run();
181 }
182 }
183 }
184
185 /***
186 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface#step()
187 */
188 public void step() throws SimRuntimeException
189 {
190 if (this.isRunning())
191 {
192 throw new SimRuntimeException("Cannot step a running simulator");
193 }
194 if (this.replication == null)
195 {
196 throw new SimRuntimeException("Cannot step a simulator "
197 + "without replication details");
198 }
199 if (this.simulatorTime >= this.replication.getRunControl()
200 .getRunLength())
201 {
202 throw new SimRuntimeException("Cannot step simulator: "
203 + "SimulatorTime = runControl.runLength");
204 }
205 Logger.finer(this, "step", "OK");
206 this.fireEvent(SimulatorInterface.STEP_EVENT, null);
207 }
208
209 /***
210 * @see nl.tudelft.simulation.dsol.simulators.SimulatorInterface#stop()
211 */
212 public void stop()
213 {
214 if (this.isRunning())
215 {
216 this.running = false;
217 Logger.finer(this, "stop", "OK");
218 if (this.simulatorTime >= this.getReplication().getRunControl()
219 .getRunLength())
220 {
221 this
222 .fireEvent(new Event(
223 SimulatorInterface.END_OF_REPLICATION_EVENT,
224 this, null));
225 }
226 this.fireEvent(SimulatorInterface.STOP_EVENT, null);
227 }
228 }
229 }