forked from metin-server/m2dev-client-src
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.
This commit is contained in:
@@ -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<size_t>(std::thread::hardware_concurrency(), packFiles.size());
|
||||
const size_t packsPerThread = (packFiles.size() + numThreads - 1) / numThreads;
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(numThreads); // Pre-allocate to prevent reallocation
|
||||
std::atomic<size_t> 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user