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-2024 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// ===========================================================================
51GUIRunThread::GUIRunThread(FXApp* app, MFXInterThreadEventClient* parent, double& simDelay,
53 MFXSingleEventThread(app, parent),
54 myNet(nullptr),
55 myHalting(true),
56 myQuit(false),
57 mySimulationInProgress(false),
58 myOk(true),
59 myHaveSignaledEnd(false),
60 mySimDelay(simDelay),
61 myEventQue(eq),
62 myEventThrow(ev),
63 myLastEndMillis(-1),
64 myLastBreakMillis(0),
65 myAmLibsumo(false) {
69}
70
71
73 // the thread shall stop
74 myQuit = true;
75 deleteSim();
76 delete myErrorRetriever;
77 delete myMessageRetriever;
78 delete myWarningRetriever;
79 // wait for the thread
80 while (mySimulationInProgress || myNet != nullptr);
81}
82
83
84bool
86 assert(net != 0);
87 // assign new values
88 myOk = true;
89 myNet = net;
90 mySimStartTime = start;
91 mySimEndTime = end;
92 myHaveSignaledEnd = false;
93 // register message callbacks
96 if (!OptionsCont::getOptions().getBool("no-warnings")) {
98 }
99 // preload the routes especially for TraCI
100 mySimulationLock.lock();
101 try {
102 net->setCurrentTimeStep(start);
103 net->loadRoutes();
104 } catch (ProcessError& e2) {
105 if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
106 WRITE_ERROR(e2.what());
107 }
108 MsgHandler::getErrorInstance()->inform(TL("Quitting (on error)."), false);
109 myHalting = true;
110 myOk = false;
112#ifndef _DEBUG
113 } catch (...) {
114 MsgHandler::getErrorInstance()->inform(TL("Quitting (on error)."), false);
115 myHalting = true;
116 myOk = false;
118#endif
119 }
120 mySimulationLock.unlock();
121 return myOk;
122}
123
124
125FXint
127 // perform an endless loop
128 while (!myQuit) {
129 if (myAmLibsumo) {
130 myApp->run();
131 } else {
132 // if the simulation shall be performed, do it
133 tryStep();
134 }
135 }
136 // delete a maybe existing simulation at the end
137 deleteSim();
138 return 0;
139}
140
141
142void
144 if (!myHalting && myNet != nullptr && myOk) {
145 const long beg = SysUtils::getCurrentMillis();
146 if (myLastEndMillis != -1) {
147 getNet().setIdleDuration((int)(beg - myLastEndMillis));
148 }
149 // check whether we shall stop at this step
150 myBreakpointLock.lock();
151 const bool haltAfter = std::find(myBreakpoints.begin(), myBreakpoints.end(), myNet->getCurrentTimeStep()) != myBreakpoints.end();
152 myBreakpointLock.unlock();
153 // stop after this step if wished
154 if (haltAfter) {
155 stop();
156 }
157 // stop the execution when only a single step should have been performed
158 if (mySingle) {
159 myHalting = true;
160 }
161 // do the step
162 makeStep();
164 // wait if wanted (delay is per simulated second)
165 long wait = (long)(mySimDelay * TS);
167 getNet().setSimDuration((int)(myLastEndMillis - beg));
168 wait -= (myLastEndMillis - beg);
169 if (wait > 0) {
171 sleep(wait);
172#ifndef WIN32
173 } else if (myLastEndMillis - myLastBreakMillis > 1000) {
174 // ensure redraw event is successful at least once per second (#9028)
175 sleep(100);
177#endif
178 }
179 } else {
180 // sleep if the simulation is not running
181 sleep(50);
182 }
183}
184
185
186void
188 GUIEvent* e = nullptr;
189 // simulation is being performed
191 // execute a single step
192 try {
193 mySimulationLock.lock();
196 mySimulationLock.unlock();
197
198 // inform parent that a step has been performed
199 e = new GUIEvent_SimulationStep();
202
203 e = nullptr;
205 switch (state) {
213 // ensure that files are closed (deleteSim is called a bit later by the gui thread)
214 // MSNet destructor may trigger MsgHandler (via routing device cleanup). Closing output devices here is not safe
215 // OutputDevice::closeAll();
216 myHaveSignaledEnd = true;
217 }
218 break;
219 default:
220 break;
221 }
222 if (e != nullptr) {
225 myHalting = true;
226 }
227 // simulation step is over
229 } catch (ProcessError& e2) {
230 if (std::string(e2.what()) != std::string("Process Error") && std::string(e2.what()) != std::string("")) {
231 WRITE_ERROR(e2.what());
232 }
233 MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
234 mySimulationLock.unlock();
239 myHalting = true;
240 myOk = false;
241#ifndef _DEBUG
242 } catch (...) {
243 MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
244 mySimulationLock.unlock();
249 myHalting = true;
250 myOk = false;
251#endif
252 }
253}
254
255
256void
258 mySingle = false;
259 myHalting = false;
260}
261
262
263void
265 mySingle = true;
266 myHalting = false;
267}
268
269
270void
272 // report the begin when wished
273 WRITE_MESSAGEF(TL("Simulation started with time: %."), time2string(mySimStartTime));
274 myOk = true;
275}
276
277
278void
280 mySingle = false;
281 myHalting = true;
282}
283
284
285bool
287 return myNet != nullptr;
288}
289
290
291void
315
316
317GUINet&
319 return *myNet;
320}
321
322
323void
325 myHalting = true;
326 myQuit = true;
327}
328
329
330void
331GUIRunThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
332 GUIEvent* e = new GUIEvent_Message(type, msg);
335}
336
337
338bool
340 return myNet != nullptr && myHalting;
341}
342
343
344bool
346 return myNet != nullptr && (!myHalting);
347}
348
349
350bool
352 return myNet != nullptr && myHalting;
353}
354
355
356void
359 if (mw != nullptr) {
360 for (GUIGlChildWindow* const window : mw->getViews()) {
361 window->getView()->waitForSnapshots(snapshotTime);
362 }
363 }
364}
365
366
367/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:298
#define WRITE_ERROR(msg)
Definition MsgHandler.h:304
#define TL(string)
Definition MsgHandler.h:315
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 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:456
void simulationStep()
Performs a single simulation step (locking the simulation)
Definition GUINet.cpp:233
void setSimDuration(int val)
Sets the duration of the last step's simulation part.
Definition GUINet.cpp:440
void guiSimulationStep()
Some further steps needed for gui processing.
Definition GUINet.cpp:226
double & mySimDelay
simulation delay
void singleStep()
called when the user presses the "single step"-button
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations.
GUINet * myNet
the loaded simulation network
SUMOTime mySimEndTime
FXMutex myBreakpointLock
Lock for modifying the list of breakpoints.
GUINet & getNet() const
returns the loaded network
std::vector< SUMOTime > myBreakpoints
List of breakpoints.
virtual FXint run()
starts the execution
virtual void begin()
starts the simulation (execution of one step after another)
void resume()
called when the user presses the "resume"-button
FXEX::MFXThreadEvent & myEventThrow
thrower events
virtual bool simulationIsStartable() const
check if simulation is startable
bool networkAvailable() const
returns the information whether a network has been loaded
bool myOk
flag to check if all is ok
virtual bool simulationIsStepable() const
check if simulation is stepable
bool mySimulationInProgress
information whether a simulation step is being performed
virtual bool init(GUINet *net, SUMOTime start, SUMOTime end)
initialises the thread with the new simulation
void makeStep()
make simulation step
bool myHalting
information whether the simulation is halting (is not being executed)
virtual ~GUIRunThread()
destructor
void tryStep()
try simulation step
virtual bool simulationIsStopable() const
check if simulation is stopableo
OutputDevice * myMessageRetriever
long myLastEndMillis
end of the last simulation step
bool mySingle
information whether the thread is running in single step mode
OutputDevice * myWarningRetriever
virtual void deleteSim()
deletes the existing simulation
void retrieveMessage(const MsgHandler::MsgType type, const std::string &msg)
Retrieves messages from the loading module.
void waitForSnapshots(const SUMOTime snapshotTime)
wait for snapshots
SUMOTime mySimStartTime
the times the simulation starts and ends with
bool myQuit
information whether the thread shall be stopped
void stop()
halts the simulation execution
bool myAmLibsumo
whether we are running in libsumo
void prepareDestruction()
halts the thread before it shall be deleted
long myLastBreakMillis
last time the simulation took a microsecond break for the fox event loop to catch up (#9028)
MFXSynchQue< GUIEvent * > & myEventQue
event queue
FXMutex mySimulationLock
mutex for lock simulation
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:913
SimulationState
Possible states of a simulation - running or stopped with different reasons.
Definition MSNet.h:94
@ SIMSTATE_TOO_MANY_TELEPORTS
The simulation had too many teleports.
Definition MSNet.h:110
@ SIMSTATE_NO_FURTHER_VEHICLES
The simulation does not contain further vehicles.
Definition MSNet.h:102
@ SIMSTATE_LOADING
The simulation is loading.
Definition MSNet.h:96
@ SIMSTATE_ERROR_IN_SIM
An error occurred during the simulation step.
Definition MSNet.h:106
@ SIMSTATE_CONNECTION_CLOSED
The connection to a client was closed by the client.
Definition MSNet.h:104
@ SIMSTATE_END_STEP_REACHED
The final simulation step has been performed.
Definition MSNet.h:100
static std::string getStateMessage(SimulationState state)
Returns the message to show if a certain state occurs.
Definition MSNet.cpp:934
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:320
void closeSimulation(SUMOTime start, const std::string &reason="")
Closes the simulation (all files, connections, etc.)
Definition MSNet.cpp:675
void setCurrentTimeStep(const SUMOTime step)
Sets the current simulation step (used by state loading)
Definition MSNet.h:328
SimulationState simulationState(SUMOTime stopTime) const
This method returns the current simulation state. It should not modify status.
Definition MSNet.cpp:883
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:44