(svn r25963) -Fix [FS#5758]: Mixtures of old and new flows could create cycles.

This commit is contained in:
fonsinchen 2013-11-10 15:18:49 +00:00
parent 9b68e4f864
commit 962d6d7e48
3 changed files with 12 additions and 3 deletions

View File

@ -72,7 +72,11 @@ LinkGraphJob::~LinkGraphJob()
st2->goods[this->Cargo()].node != it->first || st2->goods[this->Cargo()].node != it->first ||
(*lg)[node_id][it->first].LastUpdate() == INVALID_DATE) { (*lg)[node_id][it->first].LastUpdate() == INVALID_DATE) {
/* Edge has been removed. Delete flows. */ /* 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) { } else if ((*lg)[node_id][it->first].LastUnrestrictedUpdate() == INVALID_DATE) {
/* Edge is fully restricted. */ /* Edge is fully restricted. */
flows.RestrictFlows(to); flows.RestrictFlows(to);

View File

@ -148,7 +148,7 @@ class FlowStatMap : public std::map<StationID, FlowStat> {
public: public:
void AddFlow(StationID origin, StationID via, uint amount); void AddFlow(StationID origin, StationID via, uint amount);
void PassOnFlow(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 RestrictFlows(StationID via);
void ReleaseFlows(StationID via); void ReleaseFlows(StationID via);
void FinalizeLocalConsumption(StationID self); void FinalizeLocalConsumption(StationID self);

View File

@ -4352,18 +4352,23 @@ void FlowStatMap::FinalizeLocalConsumption(StationID self)
/** /**
* Delete all flows at a station for specific cargo and destination. * Delete all flows at a station for specific cargo and destination.
* @param via Remote station of flows to be deleted. * @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();) { for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
FlowStat &s_flows = f_it->second; FlowStat &s_flows = f_it->second;
s_flows.ChangeShare(via, INT_MIN); s_flows.ChangeShare(via, INT_MIN);
if (s_flows.GetShares()->empty()) { if (s_flows.GetShares()->empty()) {
ret.Push(f_it->first);
this->erase(f_it++); this->erase(f_it++);
} else { } else {
++f_it; ++f_it;
} }
} }
return ret;
} }
/** /**