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 <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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines