feat(resource-manager): added working singleton resource manager

all external data should now be handled through the resource manager. This will take care of location on disk as well as ownership
This commit is contained in:
2025-03-20 14:26:44 -04:00
parent 1cc21a368b
commit 08075f5108
7 changed files with 303 additions and 0 deletions

40
src/resource/meson.build Normal file
View File

@@ -0,0 +1,40 @@
# Define the library
resourceManager_sources = files(
'private/resourceManager.cpp',
'private/resourceManagerTypes.cpp'
)
resourceManager_headers = files(
'public/resourceManager.h',
'public/resourceManagerTypes.h'
)
dependencies = [
yaml_cpp_dep,
opatio_dep,
eos_dep,
quill_dep,
config_dep,
probe_dep,
mfem_dep,
macros_dep,
meshio_dep
]
libResourceHeader_dep = declare_dependency(include_directories: include_directories('public'))
# Define the libresourceManager library so it can be linked against by other parts of the build system
libresourceManager = static_library('resourceManager',
resourceManager_sources,
include_directories: include_directories('public'),
cpp_args: ['-fvisibility=default'],
dependencies: dependencies,
install : true)
resourceManager_dep = declare_dependency(
include_directories: include_directories('public'),
link_with: libresourceManager,
dependencies: dependencies
)
# Make headers accessible
install_headers(resourceManager_headers, subdir : '4DSSE/resource')

View File

@@ -0,0 +1,68 @@
#include <iostream>
#include <vector>
#include <string>
#include <filesystem>
#include "quill/LogMacros.h"
#include "resourceManager.h"
#include "resourceManagerTypes.h"
#include "debug.h"
#include "config.h"
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
ResourceManager::ResourceManager() {
std::string defaultDataDir = TOSTRING(DATA_DIR);
m_dataDir = m_config.get<std::string>("Data:Dir", defaultDataDir);
// -- Get the index file path using filesytem to make it a system safe path
std::string indexFilePath = m_dataDir + "/index.yaml";
std::filesystem::path indexFile(indexFilePath);
m_resourceConfig.loadConfig(indexFile.string());
std::vector<std::string> assets = m_resourceConfig.keys();
for (auto key : assets ) {
load(key);
}
}
std::vector<std::string> ResourceManager::getAvaliableResources() {
std::vector<std::string> resources;
resources = m_resourceConfig.keys();
return resources;
}
const Resource& ResourceManager::getResource(const std::string &name) const {
auto it = m_resources.find(name);
if (it != m_resources.end()) {
return it->second;
}
throw std::runtime_error("Resource " + name + " not found");
}
bool ResourceManager::loadResource(std::string& name) {
return load(name);
}
bool ResourceManager::load(const std::string& name) {
const std::string resourcePath = m_dataDir + "/" + m_resourceConfig.get<std::string>(name);
std::filesystem::path resourceFile(resourcePath);
if (!std::filesystem::exists(resourceFile)) {
LOG_ERROR(m_logger, "Resource file not found: {}", resourceFile.string());
return false;
}
LOG_INFO(m_logger, "Loading resource: {}", resourceFile.string());
if (m_resources.find(name) != m_resources.end()) {
LOG_INFO(m_logger, "Resource already loaded: {}", name);
return true;
}
Resource resource = createResource(name, resourcePath);
m_resources[name] = std::move(resource);
// -- Check if the resource is already in the map
return true;
}

View File

@@ -0,0 +1,41 @@
#include <string>
#include "resourceManagerTypes.h"
#include "opatIO.h"
#include "meshIO.h"
#include "eosIO.h"
#include "debug.h"
std::string getFirstSegment(const std::string& input) {
size_t pos = input.find(':');
if (pos == std::string::npos) {
// No colon found, return the entire string
return input;
} else {
// Return substring from start to the position of the first colon
return input.substr(0, pos);
}
}
Resource createResource(const std::string& type, const std::string& path) {
static const std::unordered_map<std::string, std::function<Resource(const std::string&)>> factoryMap = {
{"opac", [](const std::string& p) { return Resource(
std::make_unique<OpatIO>(p));
}},
{"mesh", [](const std::string& p) { return Resource(
std::make_unique<MeshIO>(p));
}},
{"eos", [](const std::string& p) { return Resource(
std::make_unique<EosIO>(p));
}}
// Add more mappings as needed
};
auto it = factoryMap.find(getFirstSegment(type));
if (it != factoryMap.end()) {
return it->second(path);
} else {
throw std::invalid_argument("Unknown resource type: " + type);
}
}

View File

@@ -0,0 +1,47 @@
#ifndef RESOURCE_MANAGER_H
#define RESOURCE_MANAGER_H
#include <vector>
#include <string>
#include <stdexcept>
#include <unordered_map>
#include "resourceManagerTypes.h"
#include "config.h"
#include "probe.h"
#include "quill/LogMacros.h"
class ResourceManager {
private:
ResourceManager();
ResourceManager(const ResourceManager&) = delete;
ResourceManager& operator=(const ResourceManager&) = delete;
Config& m_config = Config::getInstance();
Probe::LogManager& m_logManager = Probe::LogManager::getInstance();
quill::Logger* m_logger = m_logManager.getLogger("log");
Config m_resourceConfig;
std::string m_dataDir;
std::unordered_map<std::string, Resource> m_resources;
bool load(const std::string& name);
public:
static ResourceManager& getInstance() {
static ResourceManager instance;
return instance;
}
std::vector<std::string> getAvaliableResources();
const Resource& getResource(const std::string &name) const;
bool loadResource(std::string& name);
std::unordered_map<std::string, bool> loadAllResources();
};
#endif // RESOURCE_MANAGER_H

View File

@@ -0,0 +1,22 @@
#ifndef RESOURCE_MANAGER_TYPES_H
#define RESOURCE_MANAGER_TYPES_H
#include <memory>
#include <variant>
#include "opatIO.h"
#include "helm.h"
#include "meshIO.h"
#include "eosIO.h"
// -- Valid resource types
using Resource = std::variant<
std::unique_ptr<OpatIO>,
std::unique_ptr<MeshIO>,
std::unique_ptr<EosIO>>;
std::string getFirstSegment(const std::string& input);
Resource createResource(const std::string& type, const std::string& path);
#endif // RESOURCE_MANAGER_TYPES_H