171 lines
4.0 KiB
C++
171 lines
4.0 KiB
C++
#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
|