37#define PARALLEL_PLAN_MOVE
38#define PARALLEL_EXEC_MOVE
49 myLanes(
MSLane::dictSize()),
50 myWithVehicles2Integrate(
MSGlobals::gNumSimThreads > 1),
51 myLastLaneChange(edges.size()),
52 myInactiveCheckCollisions(
MSGlobals::gNumSimThreads > 1),
53 myMinLengthGeometryFactor(1.),
55 myThreadPool(false,
std::vector<int>(
MSGlobals::gNumThreads, 0)),
60 const std::vector<MSLane*>& lanes = edge->getLanes();
61 if (!edge->hasLaneChanger()) {
62 const int pos = lanes.front()->getNumericalID();
63 myLanes[pos].lane = lanes.front();
65 myLanes[pos].haveNeighbors =
false;
68 for (
MSLane*
const l : lanes) {
69 const int pos = l->getNumericalID();
72 myLanes[pos].haveNeighbors =
true;
82 new WorkerThread(myThreadPool);
96#ifdef PARALLEL_STOPWATCH
99 for (
MSLane*
const l : edge->getLanes()) {
100 wPlan.
add(l->getStopWatch()[0]);
103 std::cout << wPlan.
getHistory().size() <<
" lane planmove calls, average " << wPlan.
getAverage() <<
" ns, total " << wPlan.
getTotal() / double(1e9) <<
" s" << std::endl;
104 std::cout <<
myStopWatch[0].getHistory().size() <<
" planmove calls, average " <<
myStopWatch[0].getAverage() <<
" ns, total " <<
myStopWatch[0].getTotal() / double(1e9) <<
" s" << std::endl;
105 std::cout <<
myStopWatch[1].getHistory().size() <<
" execmove calls, average " <<
myStopWatch[1].getAverage() <<
" ns, total " <<
myStopWatch[1].getTotal() / double(1e9) <<
" s" << std::endl;
112 for (
MSLane* lane : lanes) {
113 myLanes[lane->getNumericalID()].amActive =
true;
122 if (!lu.
amActive && (*i)->getVehicleNumber() > 0) {
138#ifdef PARALLEL_STOPWATCH
142 std::vector<std::future<void>> results;
145 const int vehNum = (*i)->getVehicleNumber();
147 myLanes[(*i)->getNumericalID()].amActive =
false;
152 results.push_back(myThreadPool.executeAsync([i, t](
int) {
153 (*i)->planMovements(t);
161 myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
167 (*i)->planMovements(t);
172 for (
auto& r : results) {
178 myThreadPool.waitAll(
false);
182#ifdef PARALLEL_STOPWATCH
191 lane->setJunctionApproaches();
198#ifdef PARALLEL_STOPWATCH
203#ifdef PARALLEL_EXEC_MOVE
207 myThreadPool.executeAsync([lane, t](
int) {
208 lane->executeMovements(t);
211 myThreadPool.waitAll();
217 myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
219 myThreadPool.waitAll(
false);
229 (*i)->getVehicleNumber() > 0) {
230 (*i)->executeMovements(t);
232 if ((*i)->getVehicleNumber() == 0) {
233 myLanes[(*i)->getNumericalID()].amActive =
false;
239 for (
MSLane* lane : wasActive) {
240 lane->updateLengthSum();
250 for (
MSLane*
const lane : toIntegrate) {
251 const bool wasInactive = lane->getVehicleNumber() == 0;
252 lane->integrateNewVehicles();
253 if (wasInactive && lane->getVehicleNumber() > 0) {
265#ifdef PARALLEL_STOPWATCH
273 std::vector<MSLane*> toAdd;
274#ifdef PARALLEL_CHANGE_LANES
275 std::vector<const MSEdge*> recheckLaneUsage;
279 if (
myLanes[l->getNumericalID()].haveNeighbors) {
280 const MSEdge& edge = l->getEdge();
283#ifdef PARALLEL_CHANGE_LANES
286 myThreadPool.add(lane->getLaneChangeTask(t), lane->
getRNGIndex() % myThreadPool.size());
287 recheckLaneUsage.push_back(&edge);
297 if (lane->getVehicleNumber() > 0 && !lu.
amActive) {
298 toAdd.push_back(lane);
302 lane->sortManeuverReservations();
305#ifdef PARALLEL_CHANGE_LANES
314#ifdef PARALLEL_CHANGE_LANES
316 myThreadPool.waitAll(
false);
317 for (
const MSEdge* e : recheckLaneUsage) {
318 for (
MSLane*
const l : e->getLanes()) {
320 if (l->getVehicleNumber() > 0 && !lu.
amActive) {
325 l->sortManeuverReservations();
333 for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
343 if (lane->needsCollisionCheck()) {
344 lane->detectCollisions(timestep, stage);
349 lane->detectCollisions(timestep, stage);
371 const std::vector<MSLane*>& lanes = e->getLanes();
372 for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
373 (*j)->initRestrictions();
382 if (!edge->getLanes().empty()) {
#define PARALLEL_EXEC_MOVE
@ SUMO_TAG_EDGECONTROL
the internal state for edge control
void buildSegmentsFor(const MSEdge &e, const OptionsCont &oc)
Build the segments for a given edge.
Container & getContainer()
Container & getContainer()
void setJunctionApproaches()
Register junction approaches for all vehicles after velocities have been planned. This is a prerequis...
void patchActiveLanes()
Resets information whether a lane is active for all lanes.
std::vector< StopWatch< std::chrono::nanoseconds > > myStopWatch
~MSEdgeControl()
Destructor.
void setActiveLanes(std::list< MSLane * > lanes)
Reconstruct the current state.
void setAdditionalRestrictions()
apply additional restrictions
std::list< MSLane * > myActiveLanes
The list of active (not empty) lanes.
void detectCollisions(SUMOTime timestep, const std::string &stage)
Detect collisions.
MFXSynchQue< MSLane *, std::vector< MSLane * > > myWithVehicles2Integrate
A storage for lanes which shall be integrated because vehicles have moved onto them.
MSEdgeVector myEdges
Loaded edges.
void buildMesoSegments()
build meso segments after meso edge types are loaded
void executeMovements(SUMOTime t)
Executes planned vehicle movements with regards to right-of-way.
MFXSynchSet< MSLane *, std::set< MSLane *, ComparatorNumericalIdLess > > myInactiveCheckCollisions
Additional lanes for which collision checking must be performed.
LaneUsageVector myLanes
Information about lanes' number of vehicles and neighbors.
void gotActive(MSLane *l)
Informs the control that the given lane got active.
void checkCollisionForInactive(MSLane *l)
trigger collision checking for inactive lane
std::vector< SUMOTime > myLastLaneChange
The list of active (not empty) lanes.
std::set< MSLane *, ComparatorNumericalIdLess > myChangedStateLanes
Lanes which changed the state without informing the control.
void planMovements(SUMOTime t)
Compute safe velocities for all vehicles based on positions and speeds from the last time step....
void saveState(OutputDevice &out)
Saves the current state into the given stream.
void changeLanes(const SUMOTime t)
Moves (precomputes) critical vehicles.
MSEdgeControl(const std::vector< MSEdge * > &edges)
Constructor.
double myMinLengthGeometryFactor
A road/street connecting two junctions.
void changeLanes(SUMOTime t) const
Performs lane changing on this edge.
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
int getNumericalID() const
Returns the numerical id of the edge.
static MELoop * gMesoNet
mesoscopic simulation infrastructure
static double gLateralResolution
static bool gComputeLC
whether the simulationLoop is in the lane changing phase
static int gNumSimThreads
how many threads to use for simulation
static int gNumThreads
how many threads to use
Representation of a lane in the micro simulation.
int getRNGIndex() const
returns the associated RNG index
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
void removePending()
Removes a vehicle after it has ended.
A storage for options typed value containers)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
long long int getTotal() const
long long int getAverage() const
void add(const StopWatch< TimeT, ClockT > &other)
const std::vector< TimeT > & getHistory() const
Function-object for stable sorting of objects acting like Named without being derived (SUMOVehicle)
A structure holding some basic information about a simulated lane.
bool amActive
Information whether this lane is active.
bool haveNeighbors
Information whether this lane belongs to a multi-lane edge.