Extra2D/Extra2D/include/extra2d/core/registry.h

171 lines
4.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <extra2d/core/module.h>
#include <extra2d/core/types.h>
#include <array>
#include <typeindex>
#include <vector>
#include <memory>
#include <future>
namespace extra2d {
class Application;
/**
* @brief 编译期类型ID生成器
*/
using TypeId = size_t;
namespace detail {
inline TypeId nextTypeId() {
static TypeId id = 0;
return ++id;
}
template<typename T>
inline TypeId getTypeId() {
static TypeId id = nextTypeId();
return id;
}
}
/**
* @brief 模块注册表
* 管理模块的注册、拓扑排序和生命周期
*/
class Registry {
public:
static constexpr size_t MAX_MODULES = 64;
static Registry& instance();
Registry(const Registry&) = delete;
Registry& operator=(const Registry&) = delete;
/**
* @brief 注册模块
* @tparam T 模块类型
* @tparam Args 构造函数参数类型
* @param args 构造函数参数
* @return 模块指针
*/
template<typename T, typename... Args>
T* use(Args&&... args) {
static_assert(std::is_base_of_v<Module, T>, "T must derive from Module");
TypeId typeId = detail::getTypeId<T>();
// 数组查找O(n) 但 n 很小,缓存友好
for (size_t i = 0; i < moduleCount_; ++i) {
if (modules_[i].id == typeId) {
return static_cast<T*>(modules_[i].module.get());
}
}
// 添加新模块
if (moduleCount_ >= MAX_MODULES) {
return nullptr; // 模块数量超过上限
}
auto module = ptr::makeUnique<T>(std::forward<Args>(args)...);
T* ptr = module.get();
module->setApp(app_);
modules_[moduleCount_].id = typeId;
modules_[moduleCount_].module = std::move(module);
modules_[moduleCount_].valid = true;
++moduleCount_;
return ptr;
}
/**
* @brief 获取模块
* @tparam T 模块类型
* @return 模块指针,不存在返回 nullptr
*/
template<typename T>
T* get() const {
TypeId typeId = detail::getTypeId<T>();
for (size_t i = 0; i < moduleCount_; ++i) {
if (modules_[i].id == typeId && modules_[i].valid) {
return static_cast<T*>(modules_[i].module.get());
}
}
return nullptr;
}
/**
* @brief 获取模块(基类版本)
* @param typeIdx 类型索引
* @return 模块指针
*/
Module* get(std::type_index typeIdx) const {
// 这里仍然使用type_index作为后备方案
for (size_t i = 0; i < moduleCount_; ++i) {
if (modules_[i].valid &&
std::type_index(typeid(*modules_[i].module)) == typeIdx) {
return modules_[i].module.get();
}
}
return nullptr;
}
/**
* @brief 设置Application
*/
void setApp(Application* app) { app_ = app; }
/**
* @brief 初始化所有模块(按优先级拓扑排序,支持并行初始化)
* @return 初始化成功返回 true
*/
bool init();
/**
* @brief 关闭所有模块
*/
void shutdown();
/**
* @brief 清空所有模块
*/
void clear();
/**
* @brief 获取模块数量
*/
size_t size() const { return moduleCount_; }
private:
Registry() = default;
~Registry() = default;
struct ModuleEntry {
TypeId id = 0;
Unique<Module> module;
bool valid = false;
};
/**
* @brief 拓扑排序模块
* @return 排序后的模块列表
*/
std::vector<Module*> sort();
/**
* @brief 按层级对模块进行分组
* 同一层级的模块没有相互依赖,可以并行初始化
* @return 按层级分组的模块列表
*/
std::vector<std::vector<Module*>> group();
std::array<ModuleEntry, MAX_MODULES> modules_;
size_t moduleCount_ = 0;
Application* app_ = nullptr;
};
} // namespace extra2d