LCOV - code coverage report
Current view: top level - src/microsim - MSEdgeControl.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 134 134
Test Date: 2025-11-13 15:38:19 Functions: 100.0 % 14 14

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MSEdgeControl.cpp
      15              : /// @author  Christian Roessel
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Michael Behrisch
      19              : /// @date    Mon, 09 Apr 2001
      20              : ///
      21              : // Stores edges and lanes, performs moving of vehicle
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <iostream>
      26              : #include <queue>
      27              : #include <vector>
      28              : #include "MSEdgeControl.h"
      29              : #include "MSVehicleControl.h"
      30              : #include "MSGlobals.h"
      31              : #include "MSEdge.h"
      32              : #include "MSLane.h"
      33              : #include "MSVehicle.h"
      34              : 
      35              : #define PARALLEL_PLAN_MOVE
      36              : #define PARALLEL_EXEC_MOVE
      37              : //#define PARALLEL_CHANGE_LANES
      38              : //#define LOAD_BALANCING
      39              : 
      40              : //#define PARALLEL_STOPWATCH
      41              : 
      42              : // ===========================================================================
      43              : // member method definitions
      44              : // ===========================================================================
      45        38586 : MSEdgeControl::MSEdgeControl(const std::vector< MSEdge* >& edges)
      46        38586 :     : myEdges(edges),
      47        38586 :       myLanes(MSLane::dictSize()),
      48        38586 :       myWithVehicles2Integrate(MSGlobals::gNumSimThreads > 1),
      49        38586 :       myLastLaneChange(edges.size()),
      50        38586 :       myInactiveCheckCollisions(MSGlobals::gNumSimThreads > 1),
      51        38586 :       myMinLengthGeometryFactor(1.),
      52              : #ifdef THREAD_POOL
      53              :       myThreadPool(false, std::vector<int>(MSGlobals::gNumThreads, 0)),
      54              : #endif
      55        38586 :       myStopWatch(3) {
      56              :     // build the usage definitions for lanes
      57      1652844 :     for (MSEdge* const edge : myEdges) {
      58              :         const std::vector<MSLane*>& lanes = edge->getLanes();
      59      1614258 :         if (!edge->hasLaneChanger()) {
      60      1212716 :             const int pos = lanes.front()->getNumericalID();
      61      1212716 :             myLanes[pos].lane = lanes.front();
      62      1212716 :             myLanes[pos].amActive = false;
      63      1212716 :             myLanes[pos].haveNeighbors = false;
      64      2425432 :             myMinLengthGeometryFactor = MIN2(edge->getLengthGeometryFactor(), myMinLengthGeometryFactor);
      65              :         } else {
      66      1123276 :             for (MSLane* const l : lanes) {
      67              :                 const int pos = l->getNumericalID();
      68       721734 :                 myLanes[pos].lane = l;
      69       721734 :                 myLanes[pos].amActive = false;
      70       721734 :                 myLanes[pos].haveNeighbors = true;
      71      1420753 :                 myMinLengthGeometryFactor = MIN2(l->getLengthGeometryFactor(), myMinLengthGeometryFactor);
      72              :             }
      73       401542 :             myLastLaneChange[edge->getNumericalID()] = -1;
      74              :         }
      75              :     }
      76              : #ifndef THREAD_POOL
      77              : #ifdef HAVE_FOX
      78        38586 :     if (MSGlobals::gNumThreads > 1) {
      79        21780 :         while (myThreadPool.size() < MSGlobals::gNumThreads) {
      80        17408 :             new WorkerThread(myThreadPool);
      81              :         }
      82              :     }
      83              : #endif
      84              : #endif
      85        38586 : }
      86              : 
      87              : 
      88        38153 : MSEdgeControl::~MSEdgeControl() {
      89              : #ifndef THREAD_POOL
      90              : #ifdef HAVE_FOX
      91        38153 :     myThreadPool.clear();
      92              : #endif
      93              : #endif
      94              : #ifdef PARALLEL_STOPWATCH
      95              :     StopWatch<std::chrono::nanoseconds> wPlan;
      96              :     for (MSEdge* const edge : myEdges) {
      97              :         for (MSLane* const l : edge->getLanes()) {
      98              :             wPlan.add(l->getStopWatch()[0]);
      99              :         }
     100              :     }
     101              :     std::cout << wPlan.getHistory().size() << " lane planmove calls, average " << wPlan.getAverage() << " ns, total " << wPlan.getTotal() / double(1e9) << " s" << std::endl;
     102              :     std::cout << myStopWatch[0].getHistory().size() << " planmove calls, average " << myStopWatch[0].getAverage() << " ns, total " << myStopWatch[0].getTotal() / double(1e9) << " s" << std::endl;
     103              :     std::cout << myStopWatch[1].getHistory().size() << " execmove calls, average " << myStopWatch[1].getAverage() << " ns, total " << myStopWatch[1].getTotal() / double(1e9) << " s" << std::endl;
     104              : #endif
     105       114459 : }
     106              : 
     107              : void
     108            7 : MSEdgeControl::setActiveLanes(std::list<MSLane*> lanes) {
     109            7 :     myActiveLanes = lanes;
     110           39 :     for (MSLane* lane : lanes) {
     111           32 :         myLanes[lane->getNumericalID()].amActive = true;
     112              :     }
     113            7 : }
     114              : 
     115              : void
     116     55828244 : MSEdgeControl::patchActiveLanes() {
     117     56468385 :     for (std::set<MSLane*, ComparatorNumericalIdLess>::iterator i = myChangedStateLanes.begin(); i != myChangedStateLanes.end(); ++i) {
     118       640141 :         LaneUsage& lu = myLanes[(*i)->getNumericalID()];
     119              :         // if the lane was inactive but is now...
     120       640141 :         if (!lu.amActive && (*i)->getVehicleNumber() > 0) {
     121              :             // ... add to active lanes and mark as such
     122       621850 :             if (lu.haveNeighbors) {
     123       487994 :                 myActiveLanes.push_front(*i);
     124              :             } else {
     125       133856 :                 myActiveLanes.push_back(*i);
     126              :             }
     127       621850 :             lu.amActive = true;
     128              :         }
     129              :     }
     130              :     myChangedStateLanes.clear();
     131     55828244 : }
     132              : 
     133              : 
     134              : void
     135     55828244 : MSEdgeControl::planMovements(SUMOTime t) {
     136              : #ifdef PARALLEL_STOPWATCH
     137              :     myStopWatch[0].start();
     138              : #endif
     139              : #ifdef THREAD_POOL
     140              :     std::vector<std::future<void>> results;
     141              : #endif
     142    144241663 :     for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
     143     88413419 :         const int vehNum = (*i)->getVehicleNumber();
     144     88413419 :         if (vehNum == 0) {
     145       363569 :             myLanes[(*i)->getNumericalID()].amActive = false;
     146       363569 :             i = myActiveLanes.erase(i);
     147              :         } else {
     148              : #ifdef THREAD_POOL
     149              :             if (MSGlobals::gNumSimThreads > 1) {
     150              :                 results.push_back(myThreadPool.executeAsync([i, t](int) {
     151              :                     (*i)->planMovements(t);
     152              :                 }, (*i)->getRNGIndex() % MSGlobals::gNumSimThreads));
     153              :                 ++i;
     154              :                 continue;
     155              :             }
     156              : #else
     157              : #ifdef HAVE_FOX
     158     88049850 :             if (MSGlobals::gNumSimThreads > 1) {
     159     14385913 :                 myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
     160              :                 ++i;
     161     14385913 :                 continue;
     162              :             }
     163              : #endif
     164              : #endif
     165     73663937 :             (*i)->planMovements(t);
     166              :             ++i;
     167              :         }
     168              :     }
     169              : #ifdef THREAD_POOL
     170              :     for (auto& r : results) {
     171              :         r.wait();
     172              :     }
     173              : #else
     174              : #ifdef HAVE_FOX
     175     55828244 :     if (MSGlobals::gNumSimThreads > 1) {
     176      5367607 :         myThreadPool.waitAll(false);
     177              :     }
     178              : #endif
     179              : #endif
     180              : #ifdef PARALLEL_STOPWATCH
     181              :     myStopWatch[0].stop();
     182              : #endif
     183     55828244 : }
     184              : 
     185              : 
     186              : void
     187     55828244 : MSEdgeControl::setJunctionApproaches() {
     188    143878094 :     for (MSLane* const lane : myActiveLanes) {
     189     88049850 :         lane->setJunctionApproaches();
     190              :     }
     191     55828244 : }
     192              : 
     193              : 
     194              : void
     195     55828244 : MSEdgeControl::executeMovements(SUMOTime t) {
     196              : #ifdef PARALLEL_STOPWATCH
     197              :     myStopWatch[1].start();
     198              : #endif
     199     55828244 :     std::vector<MSLane*> wasActive(myActiveLanes.begin(), myActiveLanes.end());
     200     55828244 :     myWithVehicles2Integrate.clear();
     201              : #ifdef PARALLEL_EXEC_MOVE
     202              : #ifdef THREAD_POOL
     203              :     if (MSGlobals::gNumSimThreads > 1) {
     204              :         for (MSLane* const lane : myActiveLanes) {
     205              :             myThreadPool.executeAsync([lane, t](int) {
     206              :                 lane->executeMovements(t);
     207              :             }, lane->getRNGIndex() % MSGlobals::gNumSimThreads);
     208              :         }
     209              :         myThreadPool.waitAll();
     210              :     }
     211              : #else
     212              : #ifdef HAVE_FOX
     213     55828244 :     if (MSGlobals::gNumSimThreads > 1) {
     214     19753520 :         for (MSLane* const lane : myActiveLanes) {
     215     14385913 :             myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
     216              :         }
     217      5367607 :         myThreadPool.waitAll(false);
     218              :     }
     219              : #endif
     220              : #endif
     221              : #endif
     222    143878091 :     for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
     223              :         if (
     224              : #ifdef PARALLEL_EXEC_MOVE
     225     88049850 :             MSGlobals::gNumSimThreads <= 1 &&
     226              : #endif
     227     73663937 :             (*i)->getVehicleNumber() > 0) {
     228     73663937 :             (*i)->executeMovements(t);
     229              :         }
     230     88049847 :         if ((*i)->getVehicleNumber() == 0) {
     231      6944416 :             myLanes[(*i)->getNumericalID()].amActive = false;
     232      6944416 :             i = myActiveLanes.erase(i);
     233              :         } else {
     234              :             ++i;
     235              :         }
     236              :     }
     237    143878088 :     for (MSLane* lane : wasActive) {
     238     88049847 :         lane->updateLengthSum();
     239              :     }
     240              :     // arrived vehicles should not influence lane changing
     241     55828241 :     MSNet::getInstance()->getVehicleControl().removePending();
     242              :     std::vector<MSLane*>& toIntegrate = myWithVehicles2Integrate.getContainer();
     243     55828241 :     std::sort(toIntegrate.begin(), toIntegrate.end(), ComparatorIdLess());
     244              :     /// @todo: sorting only needed to account for lane-ordering dependencies.
     245              :     //This should disappear when parallelization is working. Until then it would
     246              :     //be better to use ComparatorNumericalIdLess instead of ComparatorIdLess
     247              :     myWithVehicles2Integrate.unlock();
     248     87861905 :     for (MSLane* const lane : toIntegrate) {
     249              :         const bool wasInactive = lane->getVehicleNumber() == 0;
     250     32033664 :         lane->integrateNewVehicles();
     251     32033664 :         if (wasInactive && lane->getVehicleNumber() > 0) {
     252      6373957 :             LaneUsage& lu = myLanes[lane->getNumericalID()];
     253      6373957 :             if (!lu.amActive) {
     254      6373957 :                 if (lu.haveNeighbors) {
     255      2875316 :                     myActiveLanes.push_front(lane);
     256              :                 } else {
     257      3498641 :                     myActiveLanes.push_back(lane);
     258              :                 }
     259      6373957 :                 lu.amActive = true;
     260              :             }
     261              :         }
     262              :     }
     263              : #ifdef PARALLEL_STOPWATCH
     264              :     myStopWatch[1].stop();
     265              : #endif
     266     55828244 : }
     267              : 
     268              : 
     269              : void
     270     55828241 : MSEdgeControl::changeLanes(const SUMOTime t) {
     271              :     std::vector<MSLane*> toAdd;
     272              : #ifdef PARALLEL_CHANGE_LANES
     273              :     std::vector<const MSEdge*> recheckLaneUsage;
     274              : #endif
     275     55828241 :     MSGlobals::gComputeLC = true;
     276    107510184 :     for (const MSLane* const l : myActiveLanes) {
     277     63400803 :         if (myLanes[l->getNumericalID()].haveNeighbors) {
     278              :             const MSEdge& edge = l->getEdge();
     279     51681943 :             if (myLastLaneChange[edge.getNumericalID()] != t) {
     280     40186311 :                 myLastLaneChange[edge.getNumericalID()] = t;
     281              : #ifdef PARALLEL_CHANGE_LANES
     282              :                 if (MSGlobals::gNumSimThreads > 1) {
     283              :                     MSLane* lane = edge.getLanes()[0];
     284              :                     myThreadPool.add(lane->getLaneChangeTask(t), lane->getRNGIndex() % myThreadPool.size());
     285              :                     recheckLaneUsage.push_back(&edge);
     286              :                 } else {
     287              : #endif
     288     40186311 :                     edge.changeLanes(t);
     289    120061628 :                     for (MSLane* const lane : edge.getLanes()) {
     290     79875317 :                         LaneUsage& lu = myLanes[lane->getNumericalID()];
     291              :                         //if ((*i)->getID() == "disabled") {
     292              :                         //    std::cout << SIMTIME << " vehicles=" << toString((*i)->getVehiclesSecure()) << "\n";
     293              :                         //    (*i)->releaseVehicles();
     294              :                         //}
     295     79875317 :                         if (lane->getVehicleNumber() > 0 && !lu.amActive) {
     296       331463 :                             toAdd.push_back(lane);
     297       331463 :                             lu.amActive = true;
     298              :                         }
     299     79875317 :                         if (MSGlobals::gLateralResolution > 0) {
     300     21025771 :                             lane->sortManeuverReservations();
     301              :                         }
     302              :                     }
     303              : #ifdef PARALLEL_CHANGE_LANES
     304              :                 }
     305              : #endif
     306              :             }
     307              :         } else {
     308              :             break;
     309              :         }
     310              :     }
     311              : 
     312              : #ifdef PARALLEL_CHANGE_LANES
     313              :     if (MSGlobals::gNumSimThreads > 1) {
     314              :         myThreadPool.waitAll(false);
     315              :         for (const MSEdge* e : recheckLaneUsage) {
     316              :             for (MSLane* const l : e->getLanes()) {
     317              :                 LaneUsage& lu = myLanes[l->getNumericalID()];
     318              :                 if (l->getVehicleNumber() > 0 && !lu.amActive) {
     319              :                     toAdd.push_back(l);
     320              :                     lu.amActive = true;
     321              :                 }
     322              :                 if (MSGlobals::gLateralResolution > 0) {
     323              :                     l->sortManeuverReservations();
     324              :                 }
     325              :             }
     326              :         }
     327              :     }
     328              : #endif
     329              : 
     330     55828241 :     MSGlobals::gComputeLC = false;
     331     56159704 :     for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
     332       331463 :         myActiveLanes.push_front(*i);
     333              :     }
     334     55828241 : }
     335              : 
     336              : 
     337              : void
     338    223323065 : MSEdgeControl::detectCollisions(SUMOTime timestep, const std::string& stage) {
     339              :     // Detections is made by the edge's lanes, therefore hand over.
     340    574224252 :     for (MSLane* lane : myActiveLanes) {
     341    350901187 :         if (lane->needsCollisionCheck()) {
     342     94858122 :             lane->detectCollisions(timestep, stage);
     343              :         }
     344              :     }
     345    223323065 :     if (myInactiveCheckCollisions.size() > 0) {
     346       854498 :         for (MSLane* lane : myInactiveCheckCollisions.getContainer()) {
     347       540752 :             lane->detectCollisions(timestep, stage);
     348              :         }
     349       313746 :         myInactiveCheckCollisions.clear();
     350              :         myInactiveCheckCollisions.unlock();
     351              :     }
     352    223323065 : }
     353              : 
     354              : 
     355              : void
     356       640588 : MSEdgeControl::gotActive(MSLane* l) {
     357              :     myChangedStateLanes.insert(l);
     358       640588 : }
     359              : 
     360              : void
     361       541791 : MSEdgeControl::checkCollisionForInactive(MSLane* l) {
     362       541791 :     myInactiveCheckCollisions.insert(l);
     363       541791 : }
     364              : 
     365              : void
     366           65 : MSEdgeControl::setAdditionalRestrictions() {
     367         2163 :     for (MSEdge* e : myEdges) {
     368         2098 :         e->inferEdgeType();
     369              :         const std::vector<MSLane*>& lanes = e->getLanes();
     370         4762 :         for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
     371         2664 :             (*j)->initRestrictions();
     372              :         }
     373              :     }
     374           65 : }
     375              : 
     376              : void
     377           41 : MSEdgeControl::setMesoTypes() {
     378          654 :     for (MSEdge* edge : myEdges) {
     379          613 :         edge->updateMesoType();
     380              :     }
     381           41 : }
     382              : 
     383              : void
     384            7 : MSEdgeControl::saveState(OutputDevice& out) {
     385            7 :     out.openTag(SUMO_TAG_EDGECONTROL);
     386            7 :     out.writeAttr(SUMO_ATTR_LANES, myActiveLanes);
     387            7 :     out.closeTag();
     388            7 : }
     389              : 
     390              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1