SUMO - Simulation of Urban MObility

GUIRunThread.cpp

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