SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // The thread that runs the simulation 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This file is part of SUMO. 00016 // SUMO is free software: you can redistribute it and/or modify 00017 // it under the terms of the GNU General Public License as published by 00018 // the Free Software Foundation, either version 3 of the License, or 00019 // (at your option) any later version. 00020 // 00021 /****************************************************************************/ 00022 00023 00024 // =========================================================================== 00025 // included modules 00026 // =========================================================================== 00027 #ifdef _MSC_VER 00028 #include <windows_config.h> 00029 #else 00030 #include <config.h> 00031 #endif 00032 00033 #include <cassert> 00034 #include <string> 00035 #include <iostream> 00036 #include <algorithm> 00037 00038 #include <guisim/GUINet.h> 00039 #include <utils/gui/events/GUIEvent_Message.h> 00040 #include <utils/gui/events/GUIEvent_SimulationStep.h> 00041 #include "GUIEvent_SimulationEnded.h" 00042 #include "GUIApplicationWindow.h" 00043 #include "GUIRunThread.h" 00044 #include "GUIGlobals.h" 00045 #include <microsim/MSVehicleControl.h> 00046 #include <utils/options/OptionsCont.h> 00047 #include <utils/common/SysUtils.h> 00048 #include <utils/common/MsgRetrievingFunction.h> 00049 #include <utils/common/MsgHandler.h> 00050 #include <utils/common/UtilExceptions.h> 00051 #include <utils/iodevices/OutputDevice.h> 00052 00053 #ifndef NO_TRACI 00054 #include <traci-server/TraCIServer.h> 00055 #endif 00056 00057 #ifdef CHECK_MEMORY_LEAKS 00058 #include <foreign/nvwa/debug_new.h> 00059 #endif // CHECK_MEMORY_LEAKS 00060 00061 00062 // =========================================================================== 00063 // used namespaces 00064 // =========================================================================== 00065 using namespace FXEX; 00066 using namespace std; 00067 00068 00069 // =========================================================================== 00070 // member method definitions 00071 // =========================================================================== 00072 GUIRunThread::GUIRunThread(FXApp* app, MFXInterThreadEventClient* parent, 00073 FXRealSpinDial& simDelay, MFXEventQue& eq, 00074 FXEX::FXThreadEvent& ev) 00075 : FXSingleEventThread(app, parent), 00076 myNet(0), myQuit(false), mySimulationInProgress(false), myOk(true), 00077 mySimDelay(simDelay), myEventQue(eq), myEventThrow(ev) { 00078 myErrorRetriever = new MsgRetrievingFunction<GUIRunThread>(this, &GUIRunThread::retrieveMessage, MsgHandler::MT_ERROR); 00079 myMessageRetriever = new MsgRetrievingFunction<GUIRunThread>(this, &GUIRunThread::retrieveMessage, MsgHandler::MT_MESSAGE); 00080 myWarningRetriever = new MsgRetrievingFunction<GUIRunThread>(this, &GUIRunThread::retrieveMessage, MsgHandler::MT_WARNING); 00081 } 00082 00083 00084 GUIRunThread::~GUIRunThread() { 00085 // the thread shall stop 00086 myQuit = true; 00087 deleteSim(); 00088 delete myErrorRetriever; 00089 delete myMessageRetriever; 00090 delete myWarningRetriever; 00091 // wait for the thread 00092 while (mySimulationInProgress || myNet != 0); 00093 } 00094 00095 00096 void 00097 GUIRunThread::init(GUINet* net, SUMOTime start, SUMOTime end) { 00098 // assign new values 00099 myNet = net; 00100 mySimStartTime = start; 00101 mySimEndTime = end; 00102 // register message callbacks 00103 MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever); 00104 MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever); 00105 MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever); 00106 } 00107 00108 00109 FXint 00110 GUIRunThread::run() { 00111 long beg = 0; 00112 long end = -1; 00113 // perform an endless loop 00114 while (!myQuit) { 00115 // if the simulation shall be perfomed, do it 00116 if (!myHalting && myNet != 0 && myOk) { 00117 if (getNet().logSimulationDuration()) { 00118 beg = SysUtils::getCurrentMillis(); 00119 if (end != -1) { 00120 getNet().setIdleDuration((int)(beg - end)); 00121 } 00122 } 00123 // check whether we shall stop at this step 00124 const bool haltAfter = find(GUIGlobals::gBreakpoints.begin(), GUIGlobals::gBreakpoints.end(), myNet->getCurrentTimeStep()) != GUIGlobals::gBreakpoints.end(); 00125 // do the step 00126 makeStep(); 00127 // stop if wished 00128 if (haltAfter) { 00129 stop(); 00130 } 00131 // wait if wanted 00132 long wait = (long) mySimDelay.getValue(); 00133 if (getNet().logSimulationDuration()) { 00134 end = SysUtils::getCurrentMillis(); 00135 getNet().setSimDuration((int)(end - beg)); 00136 wait -= (end - beg); 00137 } 00138 if (wait > 0) { 00139 sleep(wait); 00140 } 00141 } else { 00142 // sleep if the simulation is not running 00143 sleep(500); 00144 } 00145 } 00146 // delete a maybe existing simulation at the end 00147 deleteSim(); 00148 return 0; 00149 } 00150 00151 00152 void 00153 GUIRunThread::makeStep() { 00154 GUIEvent* e = 0; 00155 // simulation is being perfomed 00156 mySimulationInProgress = true; 00157 // execute a single step 00158 try { 00159 mySimulationLock.lock(); 00160 myNet->simulationStep(); 00161 myNet->guiSimulationStep(); 00162 mySimulationLock.unlock(); 00163 00164 // inform parent that a step has been performed 00165 e = new GUIEvent_SimulationStep(); 00166 myEventQue.add(e); 00167 myEventThrow.signal(); 00168 00169 e = 0; 00170 MSNet::SimulationState state = myNet->simulationState(mySimEndTime); 00171 #ifndef NO_TRACI 00172 if (state != MSNet::SIMSTATE_RUNNING) { 00173 if (OptionsCont::getOptions().getInt("remote-port") != 0 && !traci::TraCIServer::wasClosed()) { 00174 state = MSNet::SIMSTATE_RUNNING; 00175 } 00176 } 00177 #endif 00178 switch (state) { 00179 case MSNet::SIMSTATE_END_STEP_REACHED: 00180 case MSNet::SIMSTATE_NO_FURTHER_VEHICLES: 00181 case MSNet::SIMSTATE_CONNECTION_CLOSED: 00182 case MSNet::SIMSTATE_TOO_MANY_VEHICLES: 00183 WRITE_MESSAGE("Simulation ended at time: " + time2string(myNet->getCurrentTimeStep())); 00184 WRITE_MESSAGE("Reason: " + MSNet::getStateMessage(state)); 00185 e = new GUIEvent_SimulationEnded(state, myNet->getCurrentTimeStep() - DELTA_T); 00186 break; 00187 default: 00188 break; 00189 } 00190 if (e != 0) { 00191 myEventQue.add(e); 00192 myEventThrow.signal(); 00193 myHalting = true; 00194 } 00195 // stop the execution when only a single step should have 00196 // been performed 00197 if (mySingle) { 00198 myHalting = true; 00199 } 00200 // simulation step is over 00201 mySimulationInProgress = false; 00202 } catch (ProcessError& e2) { 00203 if (string(e2.what()) != string("Process Error") && std::string(e2.what()) != string("")) { 00204 WRITE_ERROR(e2.what()); 00205 } 00206 MsgHandler::getErrorInstance()->inform("Quitting (on error).", false); 00207 mySimulationLock.unlock(); 00208 mySimulationInProgress = false; 00209 e = new GUIEvent_SimulationEnded(MSNet::SIMSTATE_ERROR_IN_SIM, myNet->getCurrentTimeStep()); 00210 myEventQue.add(e); 00211 myEventThrow.signal(); 00212 myHalting = true; 00213 myOk = false; 00214 #ifndef _DEBUG 00215 } catch (...) { 00216 mySimulationLock.unlock(); 00217 mySimulationInProgress = false; 00218 e = new GUIEvent_SimulationEnded(MSNet::SIMSTATE_ERROR_IN_SIM, myNet->getCurrentTimeStep()); 00219 myEventQue.add(e); 00220 myEventThrow.signal(); 00221 myHalting = true; 00222 myOk = false; 00223 #endif 00224 } 00225 } 00226 00227 00228 void 00229 GUIRunThread::resume() { 00230 mySingle = false; 00231 myHalting = false; 00232 } 00233 00234 00235 void 00236 GUIRunThread::singleStep() { 00237 mySingle = true; 00238 myHalting = false; 00239 } 00240 00241 00242 void 00243 GUIRunThread::begin() { 00244 // report the begin when wished 00245 WRITE_MESSAGE("Simulation started with time: " + time2string(mySimStartTime)); 00246 myOk = true; 00247 } 00248 00249 00250 void 00251 GUIRunThread::stop() { 00252 mySingle = false; 00253 myHalting = true; 00254 } 00255 00256 00257 bool 00258 GUIRunThread::simulationAvailable() const { 00259 return myNet != 0; 00260 } 00261 00262 00263 void 00264 GUIRunThread::deleteSim() { 00265 myHalting = true; 00266 // remove message callbacks 00267 MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever); 00268 MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever); 00269 MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever); 00270 // 00271 mySimulationLock.lock(); 00272 if (myNet != 0) { 00273 myNet->closeSimulation(mySimStartTime); 00274 } 00275 while (mySimulationInProgress); 00276 delete myNet; 00277 GUIGlObjectStorage::gIDStorage.clear(); 00278 myNet = 0; 00279 OutputDevice::closeAll(); 00280 mySimulationLock.unlock(); 00281 MsgHandler::cleanupOnEnd(); 00282 } 00283 00284 00285 GUINet& 00286 GUIRunThread::getNet() const { 00287 return *myNet; 00288 } 00289 00290 00291 void 00292 GUIRunThread::prepareDestruction() { 00293 myHalting = true; 00294 myQuit = true; 00295 } 00296 00297 00298 void 00299 GUIRunThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) { 00300 GUIEvent* e = new GUIEvent_Message(type, msg); 00301 myEventQue.add(e); 00302 myEventThrow.signal(); 00303 } 00304 00305 00306 bool 00307 GUIRunThread::simulationIsStartable() const { 00308 return myNet != 0 && myHalting; 00309 } 00310 00311 00312 bool 00313 GUIRunThread::simulationIsStopable() const { 00314 return myNet != 0 && (!myHalting); 00315 } 00316 00317 00318 bool 00319 GUIRunThread::simulationIsStepable() const { 00320 return myNet != 0 && myHalting; 00321 } 00322 00323 00324 00325 /****************************************************************************/ 00326