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