Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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
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
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations Needed to be deleted from the handler later on.
GUINet * myNet
the loaded simulation network
SUMOTime mySimEndTime
FXMutex myBreakpointLock
Lock for modifying the list of breakpoints.
GUINet & getNet() const
std::vector< SUMOTime > myBreakpoints
List of breakpoints.
virtual FXint run()
starts the execution
virtual void begin()
FXEX::MFXThreadEvent & myEventThrow
virtual bool simulationIsStartable() const
virtual bool simulationIsStepable() const
bool mySimulationInProgress
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)
virtual ~GUIRunThread()
destructor
virtual bool simulationIsStopable() const
OutputDevice * myMessageRetriever
long myLastEndMillis
end of the last simulation step
OutputDevice * myWarningRetriever
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
bool myAmLibsumo
whether we are running in libsumo
void prepareDestruction()
long myLastBreakMillis
last time the simulation took a microsecond break for the fox event loop to catch up (#9028)
MFXSynchQue< GUIEvent * > & myEventQue
FXMutex mySimulationLock
GUIRunThread(FXApp *app, MFXInterThreadEventClient *mw, double &simDelay, MFXSynchQue< GUIEvent * > &eq, FXEX::MFXThreadEvent &ev)
constructor
bool myHaveSignaledEnd
whether the simulation already ended
static void sleep(long ms)
FXApp * myApp
pointer to APP
void push_back(T what)
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.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
virtual void clear(bool resetInformed=true)
Clears information whether an error occurred previously and print aggregated message summary.
static void cleanupOnEnd()
Removes pending handler.
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
@ 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.
Encapsulates an object's method for using it as a message retriever.
static OptionsCont & getOptions()
Retrieves the options.
static void closeAll(bool keepErrorRetrievers=false)
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:43