From 962d6d7e4877b5d1fd8717bb08d79f1d6689a934 Mon Sep 17 00:00:00 2001 From: fonsinchen Date: Sun, 10 Nov 2013 15:18:49 +0000 Subject: (svn r25963) -Fix [FS#5758]: Mixtures of old and new flows could create cycles. --- src/linkgraph/linkgraphjob.cpp | 6 +++++- src/station_base.h | 2 +- src/station_cmd.cpp | 7 ++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index b6c1747a2..717a7305d 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -72,7 +72,11 @@ LinkGraphJob::~LinkGraphJob() st2->goods[this->Cargo()].node != it->first || (*lg)[node_id][it->first].LastUpdate() == INVALID_DATE) { /* Edge has been removed. Delete flows. */ - flows.DeleteFlows(to); + StationIDStack erased = flows.DeleteFlows(to); + /* Delete old flows for source stations which have been deleted + * from the new flows. This avoids flow cycles between old and + * new flows. */ + while (!erased.IsEmpty()) ge.flows.erase(erased.Pop()); } else if ((*lg)[node_id][it->first].LastUnrestrictedUpdate() == INVALID_DATE) { /* Edge is fully restricted. */ flows.RestrictFlows(to); diff --git a/src/station_base.h b/src/station_base.h index 1c3375a26..0e6edc7e0 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -148,7 +148,7 @@ class FlowStatMap : public std::map { public: void AddFlow(StationID origin, StationID via, uint amount); void PassOnFlow(StationID origin, StationID via, uint amount); - void DeleteFlows(StationID via); + StationIDStack DeleteFlows(StationID via); void RestrictFlows(StationID via); void ReleaseFlows(StationID via); void FinalizeLocalConsumption(StationID self); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 6ed0fbf94..0bed79582 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -4352,18 +4352,23 @@ void FlowStatMap::FinalizeLocalConsumption(StationID self) /** * Delete all flows at a station for specific cargo and destination. * @param via Remote station of flows to be deleted. + * @return IDs of source stations for which the complete FlowStat, not only a + * share, has been erased. */ -void FlowStatMap::DeleteFlows(StationID via) +StationIDStack FlowStatMap::DeleteFlows(StationID via) { + StationIDStack ret; for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) { FlowStat &s_flows = f_it->second; s_flows.ChangeShare(via, INT_MIN); if (s_flows.GetShares()->empty()) { + ret.Push(f_it->first); this->erase(f_it++); } else { ++f_it; } } + return ret; } /** -- cgit v1.2.3-70-g09d2