#pragma once #ifndef Convention_Runtime_Architecture_hpp #define Convention_Runtime_Architecture_hpp #include"Config.hpp" namespace Convention { // Interface struct ISignal { virtual ~ISignal() {} }; struct IModel { virtual std::string Save() abstract; virtual void Load(std::string_view data) abstract; }; template struct IConvertable { virtual T ConvertTo() abstract; }; template struct IConvertModel : public IModel, public IConvertable { virtual ~IConvertModel() {} }; // Instance template class SingletonModel : public IModel { private: static T& InjectInstance() { static T instance; return instance; } public: static T& Instance() { return InjectInstance(); } virtual std::string Save() override { if constexpr (std::is_base_of_v) { return Instance().Save(); } throw std::runtime_error("InvalidOperationException"); } virtual void Load(std::string_view data) override { if constexpr (std::is_base_of_v) { Instance().Load(data); } throw std::runtime_error("InvalidOperationException"); } operator T& () { return Instance(); } }; class DependenceModel : public IConvertModel { private: std::vector*> queries; public: DependenceModel(std::vector*> queries) :__init(queries) {} bool ConvertTo() { for (auto&& query : queries) { if (query->ConvertTo() == false) return false; } return true; } decltype(auto) begin() noexcept { return queries.begin(); } decltype(auto) end() noexcept { return queries.end(); } virtual void Load(std::string_view data) override { throw std::runtime_error("NotImplementedException"); } virtual string Save() override { throw std::runtime_error("NotImplementedException"); } }; class Architecture { using Type = const type_info&; using TypeID = size_t; public: void InternalReset() { // Register System RegisterHistory.clear(); UncompleteTargets.clear(); Completer.clear(); Dependences.clear(); Childs.clear(); // Event Listener SignalListener.clear(); // Linear Chain for Dependence TimelineQuenes.clear(); TimelineContentID = 0; } #pragma region Objects Registered private: std::map>>> ImplTypeQuery; std::set RegisterHistory; std::map UncompleteTargets; std::map> Completer; std::map Dependences; std::map Childs; class TypeQuery : public IConvertable { private: TypeID queryType; public: TypeQuery(TypeID queryType) :__init(queryType) {} TypeQuery(Type queryType) :queryType(queryType.hash_code()) {} virtual bool ConvertTo() override { return SingletonModel::Instance().Childs.count(queryType); } }; public: class Registering : public IConvertable { private: TypeID registerSlot; public: Registering(TypeID registerSlot) :__init(registerSlot) {} Registering(Type registerSlot) :registerSlot(registerSlot.hash_code()) {} virtual bool ConvertTo() override { return SingletonModel::Instance().Childs.count(registerSlot); } }; private: bool InternalRegisteringComplete(_Out_ std::set& InternalUpdateBuffer) { bool result = false; for (auto&& dependence : Dependences) { if (dependence.second.ConvertTo()) { InternalUpdateBuffer.insert(dependence.first); result = true; } } return result; } void InternalRegisteringUpdate(_In_ std::set& InternalUpdateBuffer) { for (auto&& complete : InternalUpdateBuffer) { Dependences.erase(complete); } for (auto&& complete : InternalUpdateBuffer) { Completer[complete](); Completer.erase(complete); } for (auto&& complete : InternalUpdateBuffer) { Childs[complete] = UncompleteTargets[complete]; UncompleteTargets.erase(complete); ImplTypeQuery.erase(complete); } } public: Registering Register(Type slot, void* target, std::function completer, std::vector dependences) { if (RegisterHistory.count(slot.hash_code())) { throw std::runtime_error("Illegal duplicate registrations"); } RegisterHistory.insert(slot.hash_code()); Completer[slot.hash_code()] = completer; UncompleteTargets[slot.hash_code()] = target; std::vector*> dependenceModel; for (auto&& type : dependences) { auto cur = std::make_shared(new TypeQuery(slot)); ImplTypeQuery[slot.hash_code()].push_back(cur); dependenceModel.push_back(cur.get()); } Dependences[slot.hash_code()] = DependenceModel(dependenceModel); std::set buffer; while (InternalRegisteringComplete(buffer)) InternalRegisteringUpdate(buffer); return Registering(slot); } template Registering Register(T* target, std::function completer, std::vector dependences) { return Register(typeid(T), target, completer, dependences); } bool Contains(Type type) const noexcept { return Childs.count(type.hash_code()); } template bool Contains() const noexcept { return Contains(typeid(T)); } void* InternalGet(Type type) const { return Childs.at(type.hash_code()); } void* Get(Type type) const { return InternalGet(type); } template T* Get() { return reinterpret_cast(Get(typeid(T))); } #pragma endregion #pragma region Signal & Update private: std::map>> SignalListener; class Listening { private : const std::function& action; TypeID type; public: Listening(const std::function& action, TypeID type) : __init(action), __init(type) {} Listening(const std::function& action, Type type) : __init(action), type(type.hash_code()) {} void StopListening() const { if (SingletonModel::Instance().SignalListener.count(type)) SingletonModel::Instance().SignalListener[type].erase(action); } }; public: template Listening AddListener(std::enable_if_t, Type> slot, std::function listener) { if (SignalListener.count(slot.hash_code()) == false) SignalListener[slot.hash_code()] = {}; const auto& action = *SignalListener[slot.hash_code()].insert([listener](const ISignal& x) { auto signal = dynamic_cast(&x); if (signal) listener(*signal); }).first; return Listening(action, slot); } template Listening AddListener(std::enable_if_t, std::function> listener) { return AddListener(typeid(Signal), listener); } void SendMessage(Type slot, const ISignal& signal) { if (SignalListener.count(slot.hash_code())) { for(auto&& action : SignalListener.at(slot.hash_code())) { action(signal); } } } template void SendMessage(std::enable_if_t, const Signal&> signal) { return SendMessage(typeid(Signal), signal); } #pragma endregion #pragma region Timeline / Chain & Update private: struct TimelineQueneEntry { std::function predicate; std::list> actions; }; struct Timeline { std::map&, int> PredicateMapper; std::vector Quene; int Context = 0; }; std::map TimelineQuenes; int TimelineContentID = 0; public: int CreateTimeline() { TimelineQuenes[TimelineContentID] = {}; return TimelineContentID++; } void AddStep(int timelineId, std::function predicate, std::list> actions) { auto&& timeline = TimelineQuenes[timelineId]; if (timeline.PredicateMapper.count(predicate)) { timeline.Quene[timeline.PredicateMapper[predicate]].actions.merge(actions); } else { int time = timeline.Quene.size(); timeline.Quene.emplace_back(); timeline.Quene.back().predicate = predicate; timeline.Quene.back().actions = actions; timeline.PredicateMapper.insert({ timeline.Quene.back().predicate, time }); } } void UpdateTimeline() { for(auto&& [_, timeline] : TimelineQuenes) { if (timeline.Quene[timeline.Context].predicate()) { for(auto&& action : timeline.Quene[timeline.Context].actions) { action(); } timeline.Context++; } } } void ResetTimelineContext(int timelineId) { TimelineQuenes[timelineId].Context = 0; } #pragma endregion }; } #endif //Convention_Runtime_Architecture_hpp