Eclipse 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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // The thread that runs the simulation
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <cassert>
25 #include <string>
26 #include <iostream>
27 #include <algorithm>
28 
29 #include <guisim/GUINet.h>
33 #include "GUIApplicationWindow.h"
34 #include "GUIRunThread.h"
35 #include "GUIGlobals.h"
39 #include <utils/common/SysUtils.h>
45 #include <libsumo/Simulation.h>
46 
47 
48 // ===========================================================================
49 // member method definitions
50 // ===========================================================================
52  double& simDelay, FXSynchQue<GUIEvent*>& eq,
53  FXEX::FXThreadEvent& ev) :
54  FXSingleEventThread(app, parent),
55  myNet(nullptr), myHalting(true), myQuit(false), mySimulationInProgress(false), myOk(true), myHaveSignaledEnd(false),
56  mySimDelay(simDelay), myEventQue(eq), myEventThrow(ev),
57  myLastBreakMillis(0) {
61 }
62 
63 
65  // the thread shall stop
66  myQuit = true;
67  deleteSim();
68  delete myErrorRetriever;
69  delete myMessageRetriever;
70  delete myWarningRetriever;
71  // wait for the thread
72  while (mySimulationInProgress || myNet != nullptr);
73 }
74 
75 
76 bool
78  assert(net != 0);
79  // assign new values
80  myOk = true;
81  myNet = net;
82  mySimStartTime = start;
83  mySimEndTime = end;
84  myHaveSignaledEnd = false;
85  // register message callbacks
88  if (!OptionsCont::getOptions().getBool("no-warnings")) {
90  }
91  // preload the routes especially for TraCI
92  mySimulationLock.lock();
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  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
107  myHalting = true;
108  myOk = false;
109  mySimulationInProgress = false;
110 #endif
111  }
112  mySimulationLock.unlock();
113  return myOk;
114 }
115 
116 
117 FXint
119  long beg = 0;
120  long end = -1;
121  // perform an endless loop
122  while (!myQuit) {
123  // if the simulation shall be perfomed, do it
124  if (!myHalting && myNet != nullptr && myOk) {
126  if (end != -1) {
127  getNet().setIdleDuration((int)(beg - end));
128  }
129  // check whether we shall stop at this step
130  myBreakpointLock.lock();
131  const bool haltAfter = std::find(myBreakpoints.begin(), myBreakpoints.end(), myNet->getCurrentTimeStep()) != myBreakpoints.end();
132  myBreakpointLock.unlock();
133  // stop after this step if wished
134  if (haltAfter) {
135  stop();
136  }
137  // stop the execution when only a single step should have
138  // been performed
139  if (mySingle) {
140  myHalting = true;
141  }
142  // do the step
143  makeStep();
145  // wait if wanted (delay is per simulated second)
146  long wait = (long)(mySimDelay * TS);
148  getNet().setSimDuration((int)(end - beg));
149  wait -= (end - beg);
150  if (wait > 0) {
151  myLastBreakMillis = end;
152  sleep(wait);
153 #ifndef WIN32
154  } else if (end - myLastBreakMillis > 1000) {
155  // ensure redraw event is successfull at least once per second (#9028)
156  sleep(100);
157  myLastBreakMillis = end;
158 #endif
159  }
160  } else {
161  // sleep if the simulation is not running
162  sleep(50);
163  }
164  }
165  // delete a maybe existing simulation at the end
166  deleteSim();
167  return 0;
168 }
169 
170 
171 void
173  GUIEvent* e = nullptr;
174  // simulation is being perfomed
175  mySimulationInProgress = true;
176  // execute a single step
177  try {
178  mySimulationLock.lock();
181  mySimulationLock.unlock();
182 
183  // inform parent that a step has been performed
184  e = new GUIEvent_SimulationStep();
187 
188  e = nullptr;
190  switch (state) {
198  // ensure that files are closed (deleteSim is called a bit later by the gui thread)
199  // MSNet destructor may trigger MsgHandler (via routing device cleanup). Closing output devices here is not safe
200  // OutputDevice::closeAll();
201  myHaveSignaledEnd = true;
202  }
203  break;
204  default:
205  break;
206  }
207  if (e != nullptr) {
210  myHalting = true;
211  }
212  // simulation step is over
213  mySimulationInProgress = false;
214  } catch (ProcessError& e2) {
215  if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
216  WRITE_ERROR(e2.what());
217  }
218  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
219  mySimulationLock.unlock();
220  mySimulationInProgress = false;
224  myHalting = true;
225  myOk = false;
226 #ifndef _DEBUG
227  } catch (...) {
228  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
229  mySimulationLock.unlock();
230  mySimulationInProgress = false;
234  myHalting = true;
235  myOk = false;
236 #endif
237  }
238 }
239 
240 
241 void
243  mySingle = false;
244  myHalting = false;
245 }
246 
247 
248 void
250  mySingle = true;
251  myHalting = false;
252 }
253 
254 
255 void
257  // report the begin when wished
258  WRITE_MESSAGE("Simulation started with time: " + time2string(mySimStartTime));
259  myOk = true;
260 }
261 
262 
263 void
265  mySingle = false;
266  myHalting = true;
267 }
268 
269 
270 bool
272  return myNet != nullptr;
273 }
274 
275 
276 void
278  myHalting = true;
279  // remove message callbacks
283  //
284  mySimulationLock.lock();
285  if (myNet != nullptr) {
287  }
288  while (mySimulationInProgress);
289  delete myNet;
291  myNet = nullptr;
293  mySimulationLock.unlock();
295 }
296 
297 
298 GUINet&
300  return *myNet;
301 }
302 
303 
304 void
306  myHalting = true;
307  myQuit = true;
308 }
309 
310 
311 void
312 GUIRunThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
313  GUIEvent* e = new GUIEvent_Message(type, msg);
316 }
317 
318 
319 bool
321  return myNet != nullptr && myHalting;
322 }
323 
324 
325 bool
327  return myNet != nullptr && (!myHalting);
328 }
329 
330 
331 bool
333  return myNet != nullptr && myHalting;
334 }
335 
336 
337 void
340  if (mw != nullptr) {
341  for (GUIGlChildWindow* const window : mw->getViews()) {
342  window->getView()->waitForSnapshots(snapshotTime);
343  }
344  }
345 }
346 
347 
348 /****************************************************************************/
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:282
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define TS
Definition: SUMOTime.h:40
long long int SUMOTime
Definition: SUMOTime.h:32
static void sleep(long ms)
void push_back(T what)
Definition: FXSynchQue.h:114
Event sent when the the simulation is over.
void clear()
Clears this container.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
const std::vector< GUIGlChildWindow * > & getViews() const
get views
static GUIMainWindow * getInstance()
get instance
A MSNet extended by some values for usage within the gui.
Definition: GUINet.h:81
void setIdleDuration(int val)
Sets the duration of the last step's idle part.
Definition: GUINet.cpp:414
void simulationStep()
Performs a single simulation step (locking the simulation)
Definition: GUINet.cpp:227
void setSimDuration(int val)
Sets the duration of the last step's simulation part.
Definition: GUINet.cpp:398
void guiSimulationStep()
Some further steps needed for gui processing.
Definition: GUINet.cpp:220
double & mySimDelay
Definition: GUIRunThread.h:150
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations Needed to be deleted from the handler later on.
Definition: GUIRunThread.h:148
GUINet * myNet
the loaded simulation network
Definition: GUIRunThread.h:121
SUMOTime mySimEndTime
Definition: GUIRunThread.h:124
FXMutex myBreakpointLock
Lock for modifying the list of breakpoints.
Definition: GUIRunThread.h:162
FXEX::FXThreadEvent & myEventThrow
Definition: GUIRunThread.h:154
GUINet & getNet() const
std::vector< SUMOTime > myBreakpoints
List of breakpoints.
Definition: GUIRunThread.h:159
virtual FXint run()
starts the execution
virtual void begin()
virtual bool simulationIsStartable() const
GUIRunThread(FXApp *app, MFXInterThreadEventClient *mw, double &simDelay, FXSynchQue< GUIEvent * > &eq, FXEX::FXThreadEvent &ev)
constructor
FXSynchQue< GUIEvent * > & myEventQue
Definition: GUIRunThread.h:152
virtual bool simulationIsStepable() const
bool mySimulationInProgress
Definition: GUIRunThread.h:136
virtual bool init(GUINet *net, SUMOTime start, SUMOTime end)
initialises the thread with the new simulation
bool myHalting
information whether the simulation is halting (is not being executed)
Definition: GUIRunThread.h:127
virtual ~GUIRunThread()
destructor
virtual bool simulationIsStopable() const
OutputDevice * myMessageRetriever
Definition: GUIRunThread.h:148
OutputDevice * myWarningRetriever
Definition: GUIRunThread.h:148
bool simulationAvailable() const
virtual void deleteSim()
void retrieveMessage(const MsgHandler::MsgType type, const std::string &msg)
Retrieves messages from the loading module.
void waitForSnapshots(const SUMOTime snapshotTime)
SUMOTime mySimStartTime
the times the simulation starts and ends with
Definition: GUIRunThread.h:124
void prepareDestruction()
long myLastBreakMillis
last time the simulation took a microsecond break for the fox event loop to catch up (#9028)
Definition: GUIRunThread.h:165
FXMutex mySimulationLock
Definition: GUIRunThread.h:156
bool myHaveSignaledEnd
whether the simulation already ended
Definition: GUIRunThread.h:144
SimulationState
Possible states of a simulation - running or stopped with different reasons.
Definition: MSNet.h:93
@ SIMSTATE_TOO_MANY_TELEPORTS
The simulation had too many teleports.
Definition: MSNet.h:109
@ SIMSTATE_NO_FURTHER_VEHICLES
The simulation does not contain further vehicles.
Definition: MSNet.h:101
@ SIMSTATE_LOADING
The simulation is loading.
Definition: MSNet.h:95
@ SIMSTATE_ERROR_IN_SIM
An error occurred during the simulation step.
Definition: MSNet.h:105
@ SIMSTATE_CONNECTION_CLOSED
The connection to a client was closed by the client.
Definition: MSNet.h:103
@ SIMSTATE_END_STEP_REACHED
The final simulation step has been performed.
Definition: MSNet.h:99
static std::string getStateMessage(SimulationState state)
Returns the message to show if a certain state occurs.
Definition: MSNet.cpp:774
SimulationState adaptToState(const SimulationState state) const
Called after a simulation step, this method adapts the current simulation state if necessary.
Definition: MSNet.cpp:753
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:318
void closeSimulation(SUMOTime start, const std::string &reason="")
Closes the simulation (all files, connections, etc.)
Definition: MSNet.cpp:545
void setCurrentTimeStep(const SUMOTime step)
Sets the current simulation step (used by state loading)
Definition: MSNet.h:326
SimulationState simulationState(SUMOTime stopTime) const
This method returns the current simulation state. It should not modify status.
Definition: MSNet.cpp:723
void loadRoutes()
loads routes for the next few steps
Definition: MSNet.cpp:417
virtual void addRetriever(OutputDevice *retriever)
Adds a further retriever to the instance responsible for a certain msg type.
Definition: MsgHandler.cpp:186
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:117
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
static void cleanupOnEnd()
Removes pending handler.
Definition: MsgHandler.cpp:265
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
Definition: MsgHandler.cpp:194
@ MT_MESSAGE
The message is only something to show.
@ MT_ERROR
The message is an error.
@ MT_WARNING
The message is a warning.
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
Definition: MsgHandler.cpp:54
Encapsulates an object's method for using it as a message retriever.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
static void closeAll(bool keepErrorRetrievers=false)
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition: SysUtils.cpp:39