SUMO - Simulation of Urban MObility

GUIRunThread.cpp

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines