From e2435c7169c427af0df1fbf539b874b4905c2834 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 2 Sep 2015 18:35:56 +0100 Subject: [PATCH] Only run trace restrict programs if they contain relevant actions. Only run in pathfinder case if deny or penalty are present. Only run in is safe waiting tile case is reserve through is present. Presence is determined at program validation time and cached in the program structure. Validator now checks for unknown non-conditional instructions. --- src/lang/english.txt | 1 + src/pathfinder/yapf/yapf_costrail.hpp | 2 +- src/pbs.cpp | 2 +- src/tracerestrict.cpp | 23 ++++++++++++++++++++--- src/tracerestrict.h | 23 +++++++++++++++++------ src/tracerestrict_gui.cpp | 3 ++- 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 49543dca3a..13b2daa5af 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2462,6 +2462,7 @@ STR_TRACE_RESTRICT_ERROR_VALIDATE_END_CONDSTACK :Validation fail STR_TRACE_RESTRICT_ERROR_VALIDATE_NO_IF :Validation failed: else/endif without opening if STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE :Validation failed: duplicate else STR_TRACE_RESTRICT_ERROR_VALIDATE_ELIF_NO_IF :Validation failed: else if without opening if +STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION :Validation failed: unknown instruction STR_TRACE_RESTRICT_ERROR_SOURCE_SAME_AS_TARGET :Source and target signals are the same STR_TRACE_RESTRICT_ERROR_CAN_T_RESET_SIGNAL :{WHITE}Can't reset signal STR_TRACE_RESTRICT_ERROR_CAN_T_COPY_PROGRAM :{WHITE}Can't copy program diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index f4ff174e43..b010fe4d8a 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -264,7 +264,7 @@ private: inline bool ExecuteTraceRestrict(Node& n, TileIndex tile, Trackdir trackdir, int& cost, TraceRestrictProgramResult &out) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); - if (prog) { + if (prog && prog->actions_used_flags & TRPAUF_PF) { prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir, &TraceRestrictPreviousSignalCallback, &n), out); if (out.flags & TRPRF_DENY) { n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; diff --git a/src/pbs.cpp b/src/pbs.cpp index 16d0358b04..78a8337cb6 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -468,7 +468,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) { if (IsRestrictedSignal(ft.m_new_tile)) { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(ft.m_new_tile, TrackdirToTrack(td)); - if (prog) { + if (prog && prog->actions_used_flags & TRPAUF_RESERVE_THROUGH) { TraceRestrictProgramResult out; prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &IsSafeWaitingPositionTraceRestrictPreviousSignalCallback, nullptr), out); if (out.flags & TRPRF_RESERVE_THROUGH) { diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 84710ce164..ff86f5c80a 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -413,12 +413,14 @@ void TraceRestrictProgram::DecrementRefCount() { /** * Validate a instruction list * Returns successful result if program seems OK - * This only validates that conditional nesting is correct, at present + * This only validates that conditional nesting is correct, + * and that all non-conditionals have a known type, at present */ -CommandCost TraceRestrictProgram::Validate(const std::vector &items) { +CommandCost TraceRestrictProgram::Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags) { // static to avoid needing to re-alloc/resize on each execution static std::vector condstack; condstack.clear(); + actions_used_flags = static_cast(0); size_t size = items.size(); for (size_t i = 0; i < size; i++) { @@ -462,6 +464,19 @@ CommandCost TraceRestrictProgram::Validate(const std::vector return_cmd_error(STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE); // instruction ran off end } } + switch (GetTraceRestrictType(item)) { + case TRIT_PF_DENY: + case TRIT_PF_PENALTY: + actions_used_flags |= TRPAUF_PF; + break; + + case TRIT_RESERVE_THROUGH: + actions_used_flags |= TRPAUF_RESERVE_THROUGH; + break; + + default: + return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION); + } } } if(!condstack.empty()) { @@ -887,7 +902,8 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u break; } - CommandCost validation_result = TraceRestrictProgram::Validate(items); + TraceRestrictProgramActionsUsedFlags actions_used_flags; + CommandCost validation_result = TraceRestrictProgram::Validate(items, actions_used_flags); if (validation_result.Failed()) { return validation_result; } @@ -897,6 +913,7 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u // move in modified program prog->items.swap(items); + prog->actions_used_flags = actions_used_flags; if (prog->items.size() == 0 && prog->refcount == 1) { // program is empty, and this tile is the only reference to it diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 63a80b9d21..1704dc4c79 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -197,6 +197,15 @@ enum TraceRestrictProgramResultFlags { }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) +/** + * Enumeration for TraceRestrictProgram::actions_used_flags + */ +enum TraceRestrictProgramActionsUsedFlags { + TRPAUF_PF = 1 << 0, ///< Pathfinder deny or penalty are present + TRPAUF_RESERVE_THROUGH = 1 << 1, ///< Reserve through action is present +}; +DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags) + /** * Execution input of a TraceRestrictProgram */ @@ -230,9 +239,10 @@ struct TraceRestrictProgramResult { struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrictprogram_pool> { std::vector items; uint32 refcount; + TraceRestrictProgramActionsUsedFlags actions_used_flags; TraceRestrictProgram() - : refcount(0) { } + : refcount(0), actions_used_flags(static_cast(0)) { } void Execute(const Train *v, const TraceRestrictProgramInput &input, TraceRestrictProgramResult &out) const; @@ -243,7 +253,7 @@ struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrict void DecrementRefCount(); - static CommandCost Validate(const std::vector &items); + static CommandCost Validate(const std::vector &items, TraceRestrictProgramActionsUsedFlags &actions_used_flags); static size_t InstructionOffsetToArrayOffset(const std::vector &items, size_t offset); @@ -285,10 +295,11 @@ struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrict return items.begin() + TraceRestrictProgram::InstructionOffsetToArrayOffset(items, instruction_offset); } - /** - * Call validation function on current program instruction list - */ - CommandCost Validate() const { return TraceRestrictProgram::Validate(items); } + /** Call validation function on current program instruction list and set actions_used_flags */ + CommandCost Validate() + { + return TraceRestrictProgram::Validate(items, actions_used_flags); + } }; /** Get TraceRestrictItem type field */ diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 0737f540a9..5125c053c3 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -1680,7 +1680,8 @@ private: items.insert(items.begin() + array_offset, item); } - return TraceRestrictProgram::Validate(items).Succeeded(); + TraceRestrictProgramActionsUsedFlags actions_used_flags; + return TraceRestrictProgram::Validate(items, actions_used_flags).Succeeded(); } /**