SUMO - Simulation of Urban MObility
GUIRunThread.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // The thread that runs the simulation
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <cassert>
27 #include <string>
28 #include <iostream>
29 #include <algorithm>
30 
31 #include <guisim/GUINet.h>
35 #include "GUIApplicationWindow.h"
36 #include "GUIRunThread.h"
37 #include "GUIGlobals.h"
41 #include <utils/common/SysUtils.h>
47 #include <libsumo/Simulation.h>
48 
49 
50 // ===========================================================================
51 // member method definitions
52 // ===========================================================================
54  double& simDelay, MFXEventQue<GUIEvent*>& eq,
56  : FXSingleEventThread(app, parent),
57  myNet(0), myHalting(true), myQuit(false), mySimulationInProgress(false), myOk(true), myHaveSignaledEnd(false),
58  mySimDelay(simDelay), myEventQue(eq), myEventThrow(ev) {
62 }
63 
64 
66  // the thread shall stop
67  myQuit = true;
68  deleteSim();
69  delete myErrorRetriever;
70  delete myMessageRetriever;
71  delete myWarningRetriever;
72  // wait for the thread
73  while (mySimulationInProgress || myNet != 0);
74 }
75 
76 
77 bool
79  assert(net != 0);
80  // assign new values
81  myOk = true;
82  myNet = net;
83  mySimStartTime = start;
84  mySimEndTime = end;
85  // register message callbacks
88  if (!OptionsCont::getOptions().getBool("no-warnings")) {
90  }
91  // preload the routes especially for TraCI
93  try {
94  net->setCurrentTimeStep(start);
95  net->loadRoutes();
96  } catch (ProcessError& e2) {
97  if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
98  WRITE_ERROR(e2.what());
99  }
100  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
101  myHalting = true;
102  myOk = false;
103  mySimulationInProgress = false;
104 #ifndef _DEBUG
105  } catch (...) {
106  myHalting = true;
107  myOk = false;
108  mySimulationInProgress = false;
109 #endif
110  }
112  return myOk;
113 }
114 
115 
116 FXint
118  long beg = 0;
119  long end = -1;
120  // perform an endless loop
121  while (!myQuit) {
122  // if the simulation shall be perfomed, do it
123  if (!myHalting && myNet != 0 && myOk) {
125  if (end != -1) {
126  getNet().setIdleDuration((int)(beg - end));
127  }
128  // check whether we shall stop at this step
129  myBreakpointLock.lock();
130  const bool haltAfter = find(myBreakpoints.begin(), myBreakpoints.end(), myNet->getCurrentTimeStep()) != myBreakpoints.end();
131  myBreakpointLock.unlock();
132  // do the step
133  makeStep();
135  // stop if wished
136  if (haltAfter) {
137  stop();
138  }
139  // wait if wanted (delay is per simulated second)
140  long wait = (long)(mySimDelay * TS);
142  getNet().setSimDuration((int)(end - beg));
143  wait -= (end - beg);
144  if (wait > 0) {
145  sleep(wait);
146  }
147  } else {
148  // sleep if the simulation is not running
149  sleep(50);
150  }
151  }
152  // delete a maybe existing simulation at the end
153  deleteSim();
154  return 0;
155 }
156 
157 
158 void
160  GUIEvent* e = 0;
161  // simulation is being perfomed
162  mySimulationInProgress = true;
163  // execute a single step
164  try {
169 
170  // inform parent that a step has been performed
171  e = new GUIEvent_SimulationStep();
172  myEventQue.add(e);
174 
175  e = 0;
177  if (state == MSNet::SIMSTATE_LOADING) {
180  } else if (state != MSNet::SIMSTATE_RUNNING) {
182  state = MSNet::SIMSTATE_RUNNING;
183  }
184  }
185  switch (state) {
192  WRITE_MESSAGE("Simulation ended at time: " + time2string(myNet->getCurrentTimeStep()));
193  WRITE_MESSAGE("Reason: " + MSNet::getStateMessage(state));
195  // ensure that files are closed (deleteSim is called a bit later by the gui thread)
196  // MSNet destructor may trigger MsgHandler (via routing device cleanup). Closing output devices here is not safe
197  // OutputDevice::closeAll();
198  myHaveSignaledEnd = true;
199  }
200  break;
201  default:
202  break;
203  }
204  if (e != 0) {
205  myEventQue.add(e);
207  myHalting = true;
208  }
209  // stop the execution when only a single step should have
210  // been performed
211  if (mySingle) {
212  myHalting = true;
213  }
214  // simulation step is over
215  mySimulationInProgress = false;
216  } catch (ProcessError& e2) {
217  if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
218  WRITE_ERROR(e2.what());
219  }
220  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
222  mySimulationInProgress = false;
224  myEventQue.add(e);
226  myHalting = true;
227  myOk = false;
228 #ifndef _DEBUG
229  } catch (...) {
231  mySimulationInProgress = false;
233  myEventQue.add(e);
235  myHalting = true;
236  myOk = false;
237 #endif
238  }
239 }
240 
241 
242 void
244  mySingle = false;
245  myHalting = false;
246 }
247 
248 
249 void
251  mySingle = true;
252  myHalting = false;
253 }
254 
255 
256 void
258  // report the begin when wished
259  WRITE_MESSAGE("Simulation started with time: " + time2string(mySimStartTime));
260  myOk = true;
261 }
262 
263 
264 void
266  mySingle = false;
267  myHalting = true;
268 }
269 
270 
271 bool
273  return myNet != 0;
274 }
275 
276 
277 void
279  myHalting = true;
280  // remove message callbacks
284  //
286  if (myNet != 0) {
288  }
289  while (mySimulationInProgress);
290  delete myNet;
292  myNet = 0;
296 }
297 
298 
299 GUINet&
301  return *myNet;
302 }
303 
304 
305 void
307  myHalting = true;
308  myQuit = true;
309 }
310 
311 
312 void
313 GUIRunThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
314  GUIEvent* e = new GUIEvent_Message(type, msg);
315  myEventQue.add(e);
317 }
318 
319 
320 bool
322  return myNet != 0 && myHalting;
323 }
324 
325 
326 bool
328  return myNet != 0 && (!myHalting);
329 }
330 
331 
332 bool
334  return myNet != 0 && myHalting;
335 }
336 
337 
338 void
341  const bool wait = find(myApplicationSnapshots.begin(), myApplicationSnapshots.end(), snapShotTime) != myApplicationSnapshots.end();
342  //std::cout << SIMTIME << "waitForSnapshots " << toString(myApplicationSnapshots) << "\n";
344  if (wait && !myHalting) {
345  sleep(50);
346  waitForSnapshots(snapShotTime);
347  }
348 }
349 
350 /****************************************************************************/
351 
Event sent when the the simulation is over.
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
The message is only something to show.
Definition: MsgHandler.h:56
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:76
long long int SUMOTime
Definition: SUMOTime.h:36
virtual FXint run()
starts the execution
GUIRunThread(FXApp *app, MFXInterThreadEventClient *mw, double &simDelay, MFXEventQue< GUIEvent *> &eq, FXEX::FXThreadEvent &ev)
constructor
virtual void deleteSim()
virtual bool init(GUINet *net, SUMOTime start, SUMOTime end)
initialises the thread with the new simulation
double & mySimDelay
Definition: GUIRunThread.h:159
void waitForSnapshots(SUMOTime snapShotTime)
void add(T what)
Definition: MFXEventQue.h:52
std::set< SUMOTime > myApplicationSnapshots
List of snapshot times.
Definition: GUIRunThread.h:174
GUINet & getNet() const
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:67
virtual bool simulationIsStopable() const
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
void setCurrentTimeStep(const SUMOTime step)
Sets the current simulation step (used by state loading)
Definition: MSNet.h:264
The final simulation step has been performed.
Definition: MSNet.h:96
void addRetriever(OutputDevice *retriever)
Adds a further retriever to the instance responsible for a certain msg type.
Definition: MsgHandler.cpp:185
std::vector< std::string > & getLoadArgs()
Definition: TraCIServer.h:250
#define TS
Definition: SUMOTime.h:45
void clear()
Clears this container.
SimulationState
Possible states of a simulation - running or stopped with different reasons.
Definition: MSNet.h:90
virtual bool simulationIsStepable() const
void setIdleDuration(int val)
Sets the duration of the last step&#39;s idle part.
Definition: GUINet.cpp:393
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition: OptionsIO.cpp:55
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
void retrieveMessage(const MsgHandler::MsgType type, const std::string &msg)
Retrieves messages from the loading module.
bool myHalting
information whether the simulation is halting (is not being executed)
Definition: GUIRunThread.h:136
bool myHaveSignaledEnd
whether the simulation already ended
Definition: GUIRunThread.h:153
The simulation does not contain further vehicles.
Definition: MSNet.h:98
An error occurred during the simulation step.
Definition: MSNet.h:102
std::vector< SUMOTime > myBreakpoints
List of breakpoints.
Definition: GUIRunThread.h:168
static void cleanupOnEnd()
Removes pending handler.
Definition: MsgHandler.cpp:272
SimulationState simulationState(SUMOTime stopTime) const
Called after a simulation step, this method returns the current simulation state. ...
Definition: MSNet.cpp:545
MFXMutex mySimulationLock
Definition: GUIRunThread.h:165
static void sleep(long ms)
virtual ~GUIRunThread()
destructor
void closeSimulation(SUMOTime start)
Closes the simulation (all files, connections, etc.)
Definition: MSNet.cpp:363
SUMOTime mySimEndTime
Definition: GUIRunThread.h:133
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
virtual bool simulationIsStartable() const
The connection to a client was closed by the client.
Definition: MSNet.h:100
The simulation is running.
Definition: MSNet.h:94
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:256
bool simulationAvailable() const
void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
Definition: MsgHandler.cpp:199
bool mySimulationInProgress
Definition: GUIRunThread.h:145
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
Definition: MsgHandler.cpp:58
OutputDevice * myWarningRetriever
Definition: GUIRunThread.h:157
GUINet * myNet
the loaded simulation network
Definition: GUIRunThread.h:130
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:248
void unlock()
release mutex lock
Definition: MFXMutex.cpp:87
OutputDevice * myMessageRetriever
Definition: GUIRunThread.h:157
The message is a warning.
Definition: MsgHandler.h:58
void setSimDuration(int val)
Sets the duration of the last step&#39;s simulation part.
Definition: GUINet.cpp:377
Encapsulates an object&#39;s method for using it as a message retriever.
The simulation is loading.
Definition: MSNet.h:92
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations Needed to be deleted from the handler later on...
Definition: GUIRunThread.h:157
void prepareDestruction()
A MSNet extended by some values for usage within the gui.
Definition: GUINet.h:82
MFXEventQue< GUIEvent * > & myEventQue
Definition: GUIRunThread.h:161
static TraCIServer * getInstance()
Definition: TraCIServer.h:73
void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:113
The simulation had too many teleports.
Definition: MSNet.h:104
void lock()
lock mutex
Definition: MFXMutex.cpp:77
FXMutex myBreakpointLock
Lock for modifying the list of breakpoints.
Definition: GUIRunThread.h:171
static void closeAll(bool keepErrorRetrievers=false)
static std::string getStateMessage(SimulationState state)
Returns the message to show if a certain state occurs.
Definition: MSNet.cpp:578
void simulationStep()
Performs a single simulation step (locking the simulation)
Definition: GUINet.cpp:220
virtual void begin()
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition: SysUtils.cpp:39
void loadRoutes()
loads routes for the next few steps
Definition: MSNet.cpp:357
FXEX::FXThreadEvent & myEventThrow
Definition: GUIRunThread.h:163
SUMOTime mySimStartTime
the times the simulation starts and ends with
Definition: GUIRunThread.h:133
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:243
void guiSimulationStep()
Some further steps needed for gui processing.
Definition: GUINet.cpp:213
static bool wasClosed()
check whether close was requested
The message is an error.
Definition: MsgHandler.h:60
FXMutex myApplicationSnapshotsLock
Lock for modifying the list of snapshot times.
Definition: GUIRunThread.h:177