diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index d7b86f0a7b..1fa6bcc72a 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include "../Context.h" #include "../core/Console.hpp" @@ -503,29 +505,61 @@ private: std::vector objects; std::vector loadedObjects; std::vector badObjects; - objects.reserve(OBJECT_ENTRY_COUNT); + objects.resize(OBJECT_ENTRY_COUNT); loadedObjects.reserve(OBJECT_ENTRY_COUNT); - for (auto ori : requiredObjects) - { - Object * loadedObject = nullptr; - if (ori != nullptr) + + // Read objects + std::mutex commonMutex; + auto batch = + [this, &commonMutex, requiredObjects, &objects, &badObjects, &loadedObjects](size_t begin, size_t end) -> void { - loadedObject = ori->LoadedObject; - if (loadedObject == nullptr) + for (size_t i = begin; i < end; i++) { - loadedObject = GetOrLoadObject(ori); - if (loadedObject == nullptr) + auto ori = requiredObjects[i]; + Object * loadedObject = nullptr; + if (ori != nullptr) { - badObjects.push_back(ori->ObjectEntry); - ReportObjectLoadProblem(&ori->ObjectEntry); - } - else - { - loadedObjects.push_back(loadedObject); + loadedObject = ori->LoadedObject; + if (loadedObject == nullptr) + { + loadedObject = _objectRepository->LoadObject(ori); + if (loadedObject == nullptr) + { + std::lock_guard guard(commonMutex); + badObjects.push_back(ori->ObjectEntry); + ReportObjectLoadProblem(&ori->ObjectEntry); + } + else + { + std::lock_guard guard(commonMutex); + loadedObjects.push_back(loadedObject); + // Connect the ori to the registered object + _objectRepository->RegisterLoadedObject(ori, loadedObject); + } + } } + objects[i] = loadedObject; } - } - objects.push_back(loadedObject); + }; + + auto partitions = std::thread::hardware_concurrency(); + auto partitionSize = (requiredObjects.size() + (partitions - 1)) / partitions; + std::vector threads; + for (size_t n = 0; n < partitions; n++) + { + auto begin = n * partitionSize; + auto end = std::min(requiredObjects.size(), begin + partitionSize); + threads.emplace_back(batch, begin, end); + } + for (auto& t : threads) + { + t.join(); + } + + // Load objects + for (auto obj : loadedObjects) + { + obj->Load(); } if (badObjects.size() > 0)