summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfonsinchen <fonsinchen@openttd.org>2013-10-19 13:17:06 +0000
committerfonsinchen <fonsinchen@openttd.org>2013-10-19 13:17:06 +0000
commit338d9861bc7800744f47e72de1b6a659540ed3b1 (patch)
treec1f6433a8011ffa605d55fd1902fc95edfe8ef1c /src
parent8fff781ca06dfdd4e60509d525fcb5c840e0e431 (diff)
downloadopenttd-338d9861bc7800744f47e72de1b6a659540ed3b1.tar.xz
(svn r25883) -Fix: Limit recursion and branching in RefreshNextHopsStats more aggressively.
Diffstat (limited to 'src')
-rw-r--r--src/vehicle.cpp30
-rw-r--r--src/vehicle_base.h2
2 files changed, 20 insertions, 12 deletions
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 78aedbf8f..3d9da8447 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -2141,8 +2141,9 @@ void Vehicle::ResetRefitCaps()
* @param has_cargo If the consist could leave the last stop where it could
* interact with cargo carrying cargo
* (i.e. not an "unload all" + "no loading" order).
+ * @return Total number of hops used.
*/
-void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities,
+uint Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities,
RefitList &refit_capacities, const Order *first, const Order *cur,
const Order *next, uint hops, bool was_refit, bool has_cargo)
{
@@ -2211,20 +2212,13 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities,
/* Resolve conditionals by recursion. */
do {
+ const Order *skip_to = NULL;
if (next->IsType(OT_CONDITIONAL)) {
- const Order *skip_to = this->orders.list->GetNextDecisionNode(
+ skip_to = this->orders.list->GetNextDecisionNode(
this->orders.list->GetOrderAt(next->GetConditionSkipToOrder()),
hops / 2);
-
- if (skip_to != NULL) {
- /* Make copies of capacity tracking lists. */
- CapacitiesMap skip_capacities = capacities;
- RefitList skip_refit_capacities = refit_capacities;
- this->RefreshNextHopsStats(skip_capacities,
- skip_refit_capacities, first, cur, skip_to, hops + 1,
- was_refit, has_cargo);
- }
}
+
if (skip_first_inc) {
/* First incrementation has to be skipped if a "real" next hop,
* different from cur, was given. */
@@ -2237,6 +2231,19 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities,
next = this->orders.list->GetNextDecisionNode(
this->orders.list->GetNext(next), hops / 2);
}
+
+ if (skip_to != NULL) {
+ /* Process the linear succession first. Skip_to is likely to
+ * point back to already seen orders. */
+
+ /* Make copies of capacity tracking lists. */
+ CapacitiesMap next_capacities = capacities;
+ RefitList next_refit_capacities = refit_capacities;
+ hops = this->RefreshNextHopsStats(next_capacities,
+ next_refit_capacities, first, cur, next, hops + 1,
+ was_refit, has_cargo);
+ next = skip_to;
+ }
} while (next != NULL && next->IsType(OT_CONDITIONAL));
if (next == NULL) break;
@@ -2278,6 +2285,7 @@ void Vehicle::RefreshNextHopsStats(CapacitiesMap &capacities,
}
}
}
+ return hops;
}
/**
diff --git a/src/vehicle_base.h b/src/vehicle_base.h
index 4eecda6cc..ef5afa568 100644
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -150,7 +150,7 @@ private:
Vehicle *next_shared; ///< pointer to the next vehicle that shares the order
Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain
- void RefreshNextHopsStats(CapacitiesMap &capacities,
+ uint RefreshNextHopsStats(CapacitiesMap &capacities,
RefitList &refit_capacities, const Order *first, const Order *cur,
const Order *next, uint hops, bool was_refit, bool has_cargo);
public: