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.dev/sumo
3// Copyright (C) 2001-2023 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>
34#include "GUIRunThread.h"
35#include "GUIGlobals.h"
45#include <libsumo/Simulation.h>
46
47
48// ===========================================================================
49// member method definitions
50// ===========================================================================
52 double& simDelay, MFXSynchQue<GUIEvent*>& eq,
54 MFXSingleEventThread(app, parent),
55 myNet(nullptr), myHalting(true), myQuit(false), mySimulationInProgress(false), myOk(true), myHaveSignaledEnd(false),
56 mySimDelay(simDelay), myEventQue(eq), myEventThrow(ev),
57 myLastEndMillis(-1), myLastBreakMillis(0), myAmLibsumo(false) {
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
76bool
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(TL("Quitting (on error)."), false);
101 myHalting = true;
102 myOk = false;
104#ifndef _DEBUG
105 } catch (...) {
106 MsgHandler::getErrorInstance()->inform(TL("Quitting (on error)."), false);
107 myHalting = true;
108 myOk = false;
110#endif
111 }
112 mySimulationLock.unlock();
113 return myOk;
114}
115
116
117FXint
119 // perform an endless loop
120 while (!myQuit) {
121 if (myAmLibsumo) {
122 myApp->run();
123 } else {
124 // if the simulation shall be performed, do it
125 tryStep();
126 }
127 }
128 // delete a maybe existing simulation at the end
129 deleteSim();
130 return 0;
131}
132
133
134void
136 if (!myHalting && myNet != nullptr && myOk) {
137 const long beg = SysUtils::getCurrentMillis();
138 if (myLastEndMillis != -1) {
139 getNet().setIdleDuration((int)(beg - myLastEndMillis));
140 }
141 // check whether we shall stop at this step
142 myBreakpointLock.lock();
143 const bool haltAfter = std::find(myBreakpoints.begin(), myBreakpoints.end(), myNet->getCurrentTimeStep()) != myBreakpoints.end();
144 myBreakpointLock.unlock();
145 // stop after this step if wished
146 if (haltAfter) {
147 stop();
148 }
149 // stop the execution when only a single step should have been performed
150 if (mySingle) {
151 myHalting = true;
152 }
153 // do the step
154 makeStep();
156 // wait if wanted (delay is per simulated second)
157 long wait = (long)(mySimDelay * TS);
159 getNet().setSimDuration((int)(myLastEndMillis - beg));
160 wait -= (myLastEndMillis - beg);
161 if (wait > 0) {
163 sleep(wait);
164#ifndef WIN32
165 } else if (myLastEndMillis - myLastBreakMillis > 1000) {
166 // ensure redraw event is successfull at least once per second (#9028)
167 sleep(100);
169#endif
170 }
171 } else {
172 // sleep if the simulation is not running
173 sleep(50);
174 }
175}
176
177
178void
180 GUIEvent* e = nullptr;
181 // simulation is being perfomed
183 // execute a single step
184 try {
185 mySimulationLock.lock();
188 mySimulationLock.unlock();
189
190 // inform parent that a step has been performed
191 e = new GUIEvent_SimulationStep();
194
195 e = nullptr;
197 switch (state) {
205 // ensure that files are closed (deleteSim is called a bit later by the gui thread)
206 // MSNet destructor may trigger MsgHandler (via routing device cleanup). Closing output devices here is not safe
207 // OutputDevice::closeAll();
208 myHaveSignaledEnd = true;
209 }
210 break;
211 default:
212 break;
213 }
214 if (e != nullptr) {
217 myHalting = true;
218 }
219 // simulation step is over
221 } catch (ProcessError& e2) {
222 if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
223 WRITE_ERROR(e2.what());
224 }
225 MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
226 mySimulationLock.unlock();
231 myHalting = true;
232 myOk = false;
233#ifndef _DEBUG
234 } catch (...) {
235 MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
236 mySimulationLock.unlock();
241 myHalting = true;
242 myOk = false;
243#endif
244 }
245}
246
247
248void
250 mySingle = false;
251 myHalting = false;
252}
253
254
255void
257 mySingle = true;
258 myHalting = false;
259}
260
261
262void
264 // report the begin when wished
265 WRITE_MESSAGEF(TL("Simulation started with time: %."), time2string(mySimStartTime));
266 myOk = true;
267}
268
269
270void
272 mySingle = false;
273 myHalting = true;
274}
275
276
277bool
279 return myNet != nullptr;
280}
281
282
283void
285 myHalting = true;
286 // flush aggregated warnings
288 // remove message callbacks
292 //
293 mySimulationLock.lock();
294 if (myNet != nullptr) {
296 }
297 while (mySimulationInProgress) {
298 sleep(50);
299 }
300 delete myNet;
302 myNet = nullptr;
304 mySimulationLock.unlock();
306}
307
308
309GUINet&
311 return *myNet;
312}
313
314
315void
317 myHalting = true;
318 myQuit = true;
319}
320
321
322void
323GUIRunThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
324 GUIEvent* e = new GUIEvent_Message(type, msg);
327}
328
329
330bool
332 return myNet != nullptr && myHalting;
333}
334
335
336bool
338 return myNet != nullptr && (!myHalting);
339}
340
341
342bool
344 return myNet != nullptr && myHalting;
345}
346
347
348void
351 if (mw != nullptr) {
352 for (GUIGlChildWindow* const window : mw->getViews()) {
353 window->getView()->waitForSnapshots(snapshotTime);
354 }
355 }
356}
357
358
359/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:273
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:279
#define TL(string)
Definition: MsgHandler.h:287
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define TS
Definition: SUMOTime.h:42
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:82
void setIdleDuration(int val)
Sets the duration of the last step's idle part.
Definition: GUINet.cpp:455
void simulationStep()
Performs a single simulation step (locking the simulation)
Definition: GUINet.cpp:232
void setSimDuration(int val)
Sets the duration of the last step's simulation part.
Definition: GUINet.cpp:439
void guiSimulationStep()
Some further steps needed for gui processing.
Definition: GUINet.cpp:225
double & mySimDelay
Definition: GUIRunThread.h:161
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations Needed to be deleted from the handler later on.
Definition: GUIRunThread.h:159
GUINet * myNet
the loaded simulation network
Definition: GUIRunThread.h:132
SUMOTime mySimEndTime
Definition: GUIRunThread.h:135
FXMutex myBreakpointLock
Lock for modifying the list of breakpoints.
Definition: GUIRunThread.h:173
GUINet & getNet() const
std::vector< SUMOTime > myBreakpoints
List of breakpoints.
Definition: GUIRunThread.h:170
virtual FXint run()
starts the execution
virtual void begin()
FXEX::MFXThreadEvent & myEventThrow
Definition: GUIRunThread.h:165
virtual bool simulationIsStartable() const
virtual bool simulationIsStepable() const
bool mySimulationInProgress
Definition: GUIRunThread.h:147
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:138
virtual ~GUIRunThread()
destructor
virtual bool simulationIsStopable() const
OutputDevice * myMessageRetriever
Definition: GUIRunThread.h:159
long myLastEndMillis
end of the last simulation step
Definition: GUIRunThread.h:176
OutputDevice * myWarningRetriever
Definition: GUIRunThread.h:159
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:135
bool myAmLibsumo
whether we are running in libsumo
Definition: GUIRunThread.h:182
void prepareDestruction()
long myLastBreakMillis
last time the simulation took a microsecond break for the fox event loop to catch up (#9028)
Definition: GUIRunThread.h:179
MFXSynchQue< GUIEvent * > & myEventQue
Definition: GUIRunThread.h:163
FXMutex mySimulationLock
Definition: GUIRunThread.h:167
GUIRunThread(FXApp *app, MFXInterThreadEventClient *mw, double &simDelay, MFXSynchQue< GUIEvent * > &eq, FXEX::MFXThreadEvent &ev)
constructor
bool myHaveSignaledEnd
whether the simulation already ended
Definition: GUIRunThread.h:155
static void sleep(long ms)
FXApp * myApp
pointer to APP
void push_back(T what)
Definition: MFXSynchQue.h:113
SimulationState adaptToState(const SimulationState state, const bool isLibsumo=false) const
Called after a simulation step, this method adapts the current simulation state if necessary.
Definition: MSNet.cpp:903
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:924
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:322
void closeSimulation(SUMOTime start, const std::string &reason="")
Closes the simulation (all files, connections, etc.)
Definition: MSNet.cpp:673
void setCurrentTimeStep(const SUMOTime step)
Sets the current simulation step (used by state loading)
Definition: MSNet.h:330
SimulationState simulationState(SUMOTime stopTime) const
This method returns the current simulation state. It should not modify status.
Definition: MSNet.cpp:873
void loadRoutes()
loads routes for the next few steps
Definition: MSNet.cpp:437
virtual void addRetriever(OutputDevice *retriever)
Adds a further retriever to the instance responsible for a certain msg type.
Definition: MsgHandler.cpp:225
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:142
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
virtual void clear(bool resetInformed=true)
Clears information whether an error occurred previously and print aggregated message summary.
Definition: MsgHandler.cpp:201
static void cleanupOnEnd()
Removes pending handler.
Definition: MsgHandler.cpp:339
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
Definition: MsgHandler.cpp:233
@ 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:60
static void closeAll(bool keepErrorRetrievers=false)
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition: SysUtils.cpp:43