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