diff --git a/src/linkgraph/flowmapper.cpp b/src/linkgraph/flowmapper.cpp index e0fe90219e..feb6be85a9 100644 --- a/src/linkgraph/flowmapper.cpp +++ b/src/linkgraph/flowmapper.cpp @@ -24,8 +24,9 @@ void FlowMapper::Run(LinkGraphJob &job) const Node prev_node = job[node_id]; StationID prev = prev_node.Station(); PathList &paths = prev_node.Paths(); - for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) { + for (PathList::reverse_iterator i = paths.rbegin(); i != paths.rend(); ++i) { Path *path = *i; + if (!path) continue; uint flow = path->GetFlow(); if (flow == 0) break; Node node = job[path->GetNode()]; diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 93158e3ded..a487238a21 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -303,7 +303,7 @@ uint Path::AddFlow(uint new_flow, LinkGraphJob &job, uint max_saturation) } new_flow = this->parent->AddFlow(new_flow, job, max_saturation); if (this->flow == 0 && new_flow > 0) { - job[this->parent->node].Paths().push_front(this); + job[this->parent->node].Paths().push_back(this); } edge.AddFlow(new_flow); } diff --git a/src/linkgraph/linkgraphjob.h b/src/linkgraph/linkgraphjob.h index cdab1ba99f..0849f63cf2 100644 --- a/src/linkgraph/linkgraphjob.h +++ b/src/linkgraph/linkgraphjob.h @@ -15,13 +15,13 @@ #include "../thread/thread.h" #include "../core/dyn_arena_alloc.hpp" #include "linkgraph.h" -#include +#include #include class LinkGraphJob; class Path; class LinkGraphJobGroup; -typedef std::list PathList; +typedef std::vector PathList; /** Type of the pool for link graph jobs. */ typedef Pool LinkGraphJobPool; diff --git a/src/linkgraph/mcf.cpp b/src/linkgraph/mcf.cpp index 7dcd7bf01c..483da91289 100644 --- a/src/linkgraph/mcf.cpp +++ b/src/linkgraph/mcf.cpp @@ -493,10 +493,9 @@ void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow) cycle_begin->ReduceFlow(flow); if (cycle_begin->GetFlow() == 0) { PathList &node_paths = this->job[cycle_begin->GetParent()->GetNode()].Paths(); - for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) { + for (PathList::reverse_iterator i = node_paths.rbegin(); i != node_paths.rend(); ++i) { if (*i == cycle_begin) { - node_paths.erase(i); - node_paths.push_back(cycle_begin); + *i = nullptr; break; } } @@ -528,30 +527,35 @@ bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next * in one path each. */ PathList &paths = this->job[next_id].Paths(); PathViaMap next_hops; - for (PathList::iterator i = paths.begin(); i != paths.end();) { + uint holes = 0; + for (PathList::reverse_iterator i = paths.rbegin(); i != paths.rend();) { Path *new_child = *i; - uint new_flow = new_child->GetFlow(); - if (new_flow == 0) break; - if (new_child->GetOrigin() == origin_id) { - PathViaMap::iterator via_it = next_hops.find(new_child->GetNode()); - if (via_it == next_hops.end()) { - next_hops[new_child->GetNode()] = new_child; - ++i; - } else { - Path *child = via_it->second; - child->AddFlow(new_flow); - new_child->ReduceFlow(new_flow); + if (new_child) { + uint new_flow = new_child->GetFlow(); + if (new_flow == 0) break; + if (new_child->GetOrigin() == origin_id) { + PathViaMap::iterator via_it = next_hops.find(new_child->GetNode()); + if (via_it == next_hops.end()) { + next_hops[new_child->GetNode()] = new_child; + } else { + Path *child = via_it->second; + child->AddFlow(new_flow); + new_child->ReduceFlow(new_flow); - /* We might hit end() with with the ++ here and skip the - * newly push_back'ed path. That's good as the flow of that - * path is 0 anyway. */ - paths.erase(i++); - paths.push_back(new_child); + *i = nullptr; + holes++; + } } } else { - ++i; + holes++; } + ++i; } + if (holes >= paths.size() / 8) { + /* remove any holes */ + paths.erase(std::remove(paths.begin(), paths.end(), nullptr), paths.end()); + } + bool found = false; /* Search the next hops for nodes we have already visited */ for (PathViaMap::iterator via_it = next_hops.begin();