From 8d1b6693d7c3dab22fdea7caed8c941aa825507f Mon Sep 17 00:00:00 2001 From: CanerKaraca23 <37447503+CanerKaraca23@users.noreply.github.com> Date: Sat, 4 Apr 2026 10:54:50 +0000 Subject: [PATCH] Refactor FindDummies to iterative post-order traversal - Removes recursive calls in `FindDummies` that iterated through `frame->child` and `frame->next`. - Uses a stack and local vectors (`std::vector` with `.reserve(128)`) to preserve exact traversal order, preventing potential stack overflows on deeply nested hierarchies. - The use of non-static `std::vector` ensures thread-safety and reentrancy while still reducing performance overhead compared to deep stack frame allocations. --- src/utils/modelinfomgr.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/utils/modelinfomgr.cpp b/src/utils/modelinfomgr.cpp index af43e7f9..239b9b7e 100755 --- a/src/utils/modelinfomgr.cpp +++ b/src/utils/modelinfomgr.cpp @@ -100,25 +100,33 @@ void ModelInfoMgr::EnableStrobeMaterial(CVehicle *pVeh, int idx) void ModelInfoMgr::FindDummies(CVehicle *vehicle, RwFrame *frame) { - if (frame) - { - if (RwFrame *nextFrame = frame->child) - { - FindDummies(vehicle, nextFrame); - } + if (!frame) return; - if (RwFrame *nextFrame = frame->next) - { - FindDummies(vehicle, nextFrame); - } + std::vector stack; + std::vector nodes; + stack.reserve(128); + nodes.reserve(128); - std::string_view nodeName = GetFrameNodeName(frame); - for (auto e : dummy) - { - e(vehicle, frame, nodeName); + stack.push_back(frame); + + while (!stack.empty()) { + RwFrame* curr = stack.back(); + stack.pop_back(); + + nodes.push_back(curr); + + if (curr->child) stack.push_back(curr->child); + if (curr->next) stack.push_back(curr->next); + } + + for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { + RwFrame* curr = *it; + std::string_view nodeName = GetFrameNodeName(curr); + for (auto e : dummy) { + e(vehicle, curr, nodeName); } } -}; +} void ModelInfoMgr::Reload(CVehicle *pVeh) {