Extra2D/include/resource/resource_cache.h

136 lines
3.1 KiB
C++

#pragma once
#include <resource/resource.h>
#include <types/ptr/intrusive_ptr.h>
#include <unordered_map>
#include <string>
#include <mutex>
#include <functional>
#include <memory>
namespace extra2d {
/**
* @brief 资源缓存模板类
*
* 管理资源的加载和缓存,支持线程安全
* T 必须是 Resource 的子类
*/
template<typename T, typename... LoadArgs>
class ResourceCache {
public:
using Loader = std::function<Ptr<T>(const std::string&, LoadArgs...)>;
ResourceCache() = default;
~ResourceCache() = default;
// 禁止拷贝
ResourceCache(const ResourceCache&) = delete;
ResourceCache& operator=(const ResourceCache&) = delete;
// 允许移动
ResourceCache(ResourceCache&&) = default;
ResourceCache& operator=(ResourceCache&&) = default;
/**
* @brief 获取资源(如果不存在则加载)
* @param path 资源路径
* @param args 加载参数
* @return 资源指针
*/
Ptr<T> get(const std::string& path, LoadArgs... args) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = cache_.find(path);
if (it != cache_.end()) {
return it->second;
}
Ptr<T> resource;
if (customLoader_) {
resource = customLoader_(path, args...);
} else {
resource = defaultLoad(path, args...);
}
if (resource && resource->isLoaded()) {
cache_[path] = resource;
}
return resource;
}
/**
* @brief 预加载资源
* @param path 资源路径
* @param args 加载参数
* @return 资源指针
*/
Ptr<T> preload(const std::string& path, LoadArgs... args) {
return get(path, args...);
}
/**
* @brief 检查资源是否已缓存
* @param path 资源路径
* @return 是否已缓存
*/
bool has(const std::string& path) const {
std::lock_guard<std::mutex> lock(mutex_);
return cache_.find(path) != cache_.end();
}
/**
* @brief 移除资源
* @param path 资源路径
*/
void remove(const std::string& path) {
std::lock_guard<std::mutex> lock(mutex_);
cache_.erase(path);
}
/**
* @brief 清空缓存
*/
void clear() {
std::lock_guard<std::mutex> lock(mutex_);
cache_.clear();
}
/**
* @brief 设置自定义加载器
* @param loader 自定义加载函数
*/
void setLoader(Loader loader) {
std::lock_guard<std::mutex> lock(mutex_);
customLoader_ = loader;
}
/**
* @brief 获取缓存大小
* @return 缓存中的资源数量
*/
size_t size() const {
std::lock_guard<std::mutex> lock(mutex_);
return cache_.size();
}
private:
mutable std::mutex mutex_;
std::unordered_map<std::string, Ptr<T>> cache_;
Loader customLoader_;
/**
* @brief 默认加载函数
*/
Ptr<T> defaultLoad(const std::string& path, LoadArgs... args) {
Ptr<T> resource = makePtr<T>();
if (resource->loadFromFile(path, args...)) {
return resource;
}
return nullptr;
}
};
} // namespace extra2d