diff --git a/include/cserver/engine/components.hpp b/include/cserver/engine/components.hpp index 9b1aa80..30742c6 100644 --- a/include/cserver/engine/components.hpp +++ b/include/cserver/engine/components.hpp @@ -223,7 +223,7 @@ public: } // namespace impl -template +template struct DependencyGraphElement {}; @@ -232,6 +232,79 @@ struct DependencyGraph { static constexpr auto kValue = utempl::TypeList{}; }; +namespace impl { + +template +struct CompileTimeStack { + std::array, Size> data{}; + std::size_t current{}; + inline constexpr auto Push(T value) { + if(this->current == Size) { + throw std::out_of_range{0}; + }; + this->data[current].emplace(std::move(value)); + this->current++; + }; + inline constexpr auto Pop() { + auto tmp = this->current; + this->current--; + return std::move(*this->data[tmp]); + }; +}; + +template +struct RangeView { + T* beginIterator; + T* endIterator; + template + inline constexpr auto begin(this Self&& self) { + return std::forward(self).beginIterator; + }; + template + inline constexpr auto end(this Self&& self) { + return std::forward(self).endIterator; + }; + inline constexpr RangeView(std::ranges::range auto&& range) : + beginIterator(std::ranges::begin(range)), + endIterator(std::ranges::end(range)) {}; +}; +RangeView(std::ranges::range auto&& range) -> RangeView>; + +} // namespace impl + +template +consteval auto TopologicalSort(const DependencyGraph...>&) { + const utempl::Tuple storage = {[&](utempl::Wrapper) { + return [&](std::index_sequence) -> std::array> { + return {utempl::Find(utempl::Tuple{Names...}, Get(DDependencies))...}; + }(std::make_index_sequence>{}); + }(utempl::Wrapper{})...}; + constexpr auto Size = utempl::kTupleSize; + const std::array adj = [&](std::index_sequence){ + return std::array{impl::RangeView{Get(storage)}...}; + }(std::make_index_sequence{}); + std::array visited{}; + constexpr auto ResultSize = sizeof...(Dependencies); + impl::CompileTimeStack response{}; + for(std::size_t i = 0; i < Size; i++) { + if(visited[i] == true) { + continue; + }; + [&](this auto&& self, std::size_t v) -> void { + visited[v] = true; + for(const auto& element : adj[v]) { + if(!visited[element]) { + self(element); + }; + }; + response.Push(v); + }(i); + }; + return utempl::Transform(std::move(response.data), [](auto&& data){ + return *data; + }); +}; + template struct ServiceContextBuilder { @@ -274,7 +347,7 @@ struct ServiceContextBuilder { static consteval auto GetDependencyGraph() { return [&] (ComponentConfig...){ - return DependencyGraph (ComponentConfig) { impl::DependencyInfoInjector injector; @@ -284,6 +357,14 @@ struct ServiceContextBuilder { }(ComponentConfigs{}...); }; + static consteval auto Sort() { + constexpr auto sorted = TopologicalSort(GetDependencyGraph()); + return [&](std::index_sequence){ + constexpr auto list = utempl::TypeList{}; + return ServiceContextBuilder(list))...>{}; + }(std::index_sequence_for{}); + }; + static constexpr auto Run() -> void { []