From 264a0a43d7c6e30b1d8bfc1fb8a3f9e40992275f Mon Sep 17 00:00:00 2001 From: SuntrustDev <19979417+SunTrustDev@users.noreply.github.com> Date: Tue, 17 Feb 2026 10:30:13 +0100 Subject: [PATCH] Fix: Reverted to sequential pack loading to avoid race conditions Loads packs one by one so that duplicate file resolution follows a deterministic order (last pack wins). Parallel loading made the effective order depend on lock acquisition order, allowing older packs to override newer ones. Sequential load stays under ~1s (~350ms on typical hardware), so the performance tradeoff is considered acceptable. --- src/UserInterface/UserInterface.cpp | 41 +++++------------------------ 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/UserInterface/UserInterface.cpp b/src/UserInterface/UserInterface.cpp index 00bd048..1cd7cf2 100644 --- a/src/UserInterface/UserInterface.cpp +++ b/src/UserInterface/UserInterface.cpp @@ -149,47 +149,20 @@ bool PackInitialize(const char * c_pszFolder) "uiloading", }; - Tracef("PackInitialize: Loading root.pck..."); + Tracef("PackInitialize: Loading root.pck\n"); + DWORD dwStartTime = GetTickCount(); if (!CPackManager::instance().AddPack(std::format("{}/root.pck", c_pszFolder))) { TraceError("Failed to load root.pck"); return false; } - Tracef("PackInitialize: Loading %d pack files in parallel...", packFiles.size()); - const size_t numThreads = std::min(std::thread::hardware_concurrency(), packFiles.size()); - const size_t packsPerThread = (packFiles.size() + numThreads - 1) / numThreads; - - std::vector threads; - threads.reserve(numThreads); // Pre-allocate to prevent reallocation - std::atomic failedCount(0); - - // Create all threads first (prevents vector reallocation during emplace_back) - for (size_t t = 0; t < numThreads; ++t) - { - size_t start = t * packsPerThread; - size_t end = std::min(start + packsPerThread, packFiles.size()); - - threads.emplace_back([&failedCount, &packFiles, c_pszFolder, start, end]() { - for (size_t i = start; i < end; ++i) - { - std::string packPath = std::format("{}/{}.pck", c_pszFolder, packFiles[i]); - if (!CPackManager::instance().AddPack(packPath)) - { - TraceError("Failed to load %s", packPath.c_str()); - failedCount++; - } - } - }); + Tracef("PackInitialize: Loading %d pack files...", packFiles.size()); + for (const std::string& packFileName : packFiles) { + Tracef("PackInitialize: Loading %s.pck\n", packFileName.c_str()); + CPackManager::instance().AddPack(std::format("{}/{}.pck", c_pszFolder, packFileName)); } - - // Wait for all threads to complete - for (auto& thread : threads) - { - thread.join(); - } - - Tracef("PackInitialize: Completed! Failed: %d / %d", failedCount.load(), packFiles.size()); + Tracef("PackInitialize: done. Time taken: %d ms\n", GetTickCount() - dwStartTime); return true; }