From c7b5336da9f2791f69a9060b947a1ea6c66e2848 Mon Sep 17 00:00:00 2001 From: Hleb Valoshka <375gnu@gmail.com> Date: Sun, 24 Dec 2023 22:17:44 +0200 Subject: [PATCH] WIP: Async load models --- src/celengine/meshmanager.h | 2 +- src/celutil/resmanager.h | 51 +++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/celengine/meshmanager.h b/src/celengine/meshmanager.h index 37a6bd36275..180594ed9f8 100644 --- a/src/celengine/meshmanager.h +++ b/src/celengine/meshmanager.h @@ -97,6 +97,6 @@ inline bool operator<(const GeometryInfo::ResourceKey& k0, std::tie(k1.resolvedPath, k1.center.x(), k1.center.y(), k1.center.z(), k1.scale, k1.isNormalized); } -using GeometryManager = ResourceManager; +using GeometryManager = ResourceManager; extern GeometryManager* GetGeometryManager(); diff --git a/src/celutil/resmanager.h b/src/celutil/resmanager.h index 1e43ae93310..232bd496e8d 100644 --- a/src/celutil/resmanager.h +++ b/src/celutil/resmanager.h @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include #include @@ -18,16 +19,19 @@ #include -enum class ResourceState { +enum class ResourceState +{ NotLoaded = 0, Loaded = 1, LoadingFailed = 2, + LoadingAsync = 3, }; -template class ResourceManager +template class ResourceManager { - public: + static constexpr bool async = A; +public: explicit ResourceManager(const fs::path& _baseDir) : baseDir(_baseDir) {}; ~ResourceManager() = default; @@ -63,13 +67,17 @@ template class ResourceManager { loadResource(resources[h]); } + else if (resources[h].state == ResourceState::LoadingAsync) + { + handleAsyncLoad(resources[h]); + } return resources[h].state == ResourceState::Loaded ? resources[h].resource.get() : nullptr; } - private: +private: using KeyType = typename T::ResourceKey; struct InfoType @@ -77,6 +85,7 @@ template class ResourceManager T info; ResourceState state{ ResourceState::NotLoaded }; std::shared_ptr resource{ nullptr }; + std::future future; explicit InfoType(T _info) : info(std::move(_info)) {} InfoType(const InfoType&) = delete; @@ -113,7 +122,39 @@ template class ResourceManager info.resource = std::move(resource); info.state = ResourceState::Loaded; } - else if (info.load(resolvedKey)) + else + { + if constexpr (async) + { + info.future = std::async(std::launch::async, [&info, resolvedKey]() + { + return info.load(resolvedKey); + }); + info.state = ResourceState::LoadingAsync; + } + else + { + bool good = info.load(resolvedKey); + finish(good, info, resolvedKey); + } + } + } + + void handleAsyncLoad(InfoType& info) + { + if constexpr (async) + { + if (info.future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + { + bool good = info.future.get(); + finish(good, info, info.resolve(baseDir)); + } + } + } + + void finish(bool good, InfoType& info, const KeyType &resolvedKey) + { + if (good) { info.state = ResourceState::Loaded; if (auto [iter, inserted] = loadedResources.try_emplace(std::move(resolvedKey), info.resource); !inserted)