diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 0caca3b18d..d1a34a39e9 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -1050,6 +1050,8 @@ Money GetGroupProfitLastYearMinAge(CompanyID company, GroupID id_g, VehicleType void RemoveAllGroupsForCompany(const CompanyID company) { + ReindexTemplateReplacementsRecursiveGuard guard; + for (Group *g : Group::Iterate()) { if (company == g->owner) { DeleteTemplateReplacementsByGroupID(g); diff --git a/src/tbtr_template_vehicle.cpp b/src/tbtr_template_vehicle.cpp index 2310594d1b..6143249464 100644 --- a/src/tbtr_template_vehicle.cpp +++ b/src/tbtr_template_vehicle.cpp @@ -47,6 +47,7 @@ INSTANTIATE_POOL_METHODS(TemplateReplacement) robin_hood::unordered_flat_map _template_replacement_index; robin_hood::unordered_flat_map _template_replacement_index_recursive; +static uint32 _template_replacement_index_recursive_guard = 0; static void MarkTrainsInGroupAsPendingTemplateReplacement(GroupID gid, const TemplateVehicle *tv); @@ -175,6 +176,8 @@ bool ShouldServiceTrainForTemplateReplacement(const Train *t, const TemplateVehi static void MarkTrainsInGroupAsPendingTemplateReplacement(GroupID gid, const TemplateVehicle *tv) { + if (_template_replacement_index_recursive_guard != 0) return; + std::vector groups; groups.push_back(gid); @@ -316,6 +319,11 @@ void ReindexTemplateReplacements() void ReindexTemplateReplacementsRecursive() { + if (_template_replacement_index_recursive_guard != 0) { + _template_replacement_index_recursive_guard |= 0x80000000; + return; + } + _template_replacement_index_recursive.clear(); for (const Group *group : Group::Iterate()) { if (group->vehicle_type != VEH_TRAIN) continue; @@ -333,8 +341,24 @@ void ReindexTemplateReplacementsRecursive() } } +ReindexTemplateReplacementsRecursiveGuard::ReindexTemplateReplacementsRecursiveGuard() +{ + _template_replacement_index_recursive_guard++; +} + +ReindexTemplateReplacementsRecursiveGuard::~ReindexTemplateReplacementsRecursiveGuard() +{ + _template_replacement_index_recursive_guard--; + if (_template_replacement_index_recursive_guard == 0x80000000) { + _template_replacement_index_recursive_guard = 0; + ReindexTemplateReplacementsRecursive(); + } +} + std::string ValidateTemplateReplacementCaches() { + assert(_template_replacement_index_recursive_guard == 0); + robin_hood::unordered_flat_map saved_template_replacement_index = std::move(_template_replacement_index); robin_hood::unordered_flat_map saved_template_replacement_index_recursive = std::move(_template_replacement_index_recursive); diff --git a/src/tbtr_template_vehicle.h b/src/tbtr_template_vehicle.h index 0958cafc92..c7b6ab7e45 100644 --- a/src/tbtr_template_vehicle.h +++ b/src/tbtr_template_vehicle.h @@ -232,6 +232,21 @@ uint DeleteTemplateReplacementsByGroupID(const Group *g); void ReindexTemplateReplacements(); void ReindexTemplateReplacementsRecursive(); +/** + * Guard to inhibit re-indexing of the recursive group to template replacement cache, + * and to disable group-based VF_REPLACEMENT_PENDING changes. + * May be used recursively. + */ +struct ReindexTemplateReplacementsRecursiveGuard { + ReindexTemplateReplacementsRecursiveGuard(); + ~ReindexTemplateReplacementsRecursiveGuard(); + + ReindexTemplateReplacementsRecursiveGuard(const ReindexTemplateReplacementsRecursiveGuard ©src) = delete; + ReindexTemplateReplacementsRecursiveGuard(ReindexTemplateReplacementsRecursiveGuard &&movesrc) = delete; + ReindexTemplateReplacementsRecursiveGuard &operator=(const ReindexTemplateReplacementsRecursiveGuard &) = delete; + ReindexTemplateReplacementsRecursiveGuard &operator=(ReindexTemplateReplacementsRecursiveGuard &&) = delete; +}; + int GetTemplateVehicleEstimatedMaxAchievableSpeed(const TemplateVehicle *tv, int mass, const int speed_cap); #endif /* TEMPLATE_VEH_H */