Move operations for working with dependencies into a separate class

This commit is contained in:
sha512sum 2024-06-28 05:04:14 +00:00
parent 0b738d4e7c
commit 1fa4a48ddc
2 changed files with 69 additions and 68 deletions

View file

@ -134,7 +134,7 @@ inline constexpr auto InitComponents(T& ccontext) -> void {
for(auto* flag : dependencies) { for(auto* flag : dependencies) {
co_await flag->AsyncWait(); co_await flag->AsyncWait();
}; };
Get<Is>(context.storage).emplace(utempl::Wrapper<Get<Is>(T::kNames)>{}, context); Get<Is>(context.storage).emplace(utempl::Wrapper<Get<Is>(T::kUtils.kNames)>{}, context);
auto& componentInitFlag = GetInitFlagFor<AsyncConditionVariable, Is>(ioContext); auto& componentInitFlag = GetInitFlagFor<AsyncConditionVariable, Is>(ioContext);
componentInitFlag.NotifyAll(); componentInitFlag.NotifyAll();
if constexpr(requires{Get<Is>(context.storage)->Run();}) { if constexpr(requires{Get<Is>(context.storage)->Run();}) {
@ -144,6 +144,49 @@ inline constexpr auto InitComponents(T& ccontext) -> void {
}(std::make_index_sequence<utempl::kTupleSize<decltype(DependencyGraph)>>()); }(std::make_index_sequence<utempl::kTupleSize<decltype(DependencyGraph)>>());
}; };
template <typename... Ts>
struct DependenciesUtils {
static constexpr utempl::TypeList<typename Ts::Type...> kTypeList;
static constexpr auto kOptions = utempl::Tuple{Ts::kOptions...};
static constexpr auto kNames = utempl::Tuple{Ts::kName...};
static constexpr utempl::TypeList<Ts...> kComponentConfigs;
template <typename T>
static consteval auto GetIndexByType() -> std::size_t {
return utempl::Find<std::remove_cvref_t<T>>(kTypeList);
};
template <std::size_t N>
static consteval auto GetIndexByName(const utempl::ConstexprString<N>& name) -> std::size_t {
return utempl::Find(kNames, name);
};
template <template <typename...> typename F>
static consteval auto GetFirstIndex() -> std::size_t {
constexpr auto arr = std::array<std::size_t, sizeof...(Ts)>({F<typename Ts::Type>::value...});
return std::ranges::find(arr, true) - arr.begin();
};
template <template <typename...> typename F>
static consteval auto GetAllIndexes() {
return [&](auto... is) {
return utempl::TupleCat(std::array<std::size_t, 0>{}, [&]{
if constexpr(F<typename Ts::Type>::value) {
return std::to_array<std::size_t>({is});
} else {
return std::array<std::size_t, 0>{};
};
}()...);} | utempl::kSeq<sizeof...(Ts)>;
};
template <std::size_t I>
static consteval auto GetName() {
return Get<I>(kNames);
};
};
} // namespace impl } // namespace impl
#define COMPONENT_REQUIRES(name, impl) \ #define COMPONENT_REQUIRES(name, impl) \
@ -155,14 +198,14 @@ inline constexpr auto InitComponents(T& ccontext) -> void {
} }
template <ConstexprConfig config, utempl::Tuple DependencyGraph, auto names, auto Options, typename... Ts> template <ConstexprConfig config, utempl::Tuple DependencyGraph, typename... Ts>
struct ServiceContext { struct ServiceContext {
static constexpr auto kNames = names;
static constexpr auto kConfig = config; static constexpr auto kConfig = config;
static constexpr auto kList = utempl::TypeList<Ts...>{};
static constexpr auto kThreadsCount = config.template Get<"threads">(); static constexpr auto kThreadsCount = config.template Get<"threads">();
static constexpr impl::DependenciesUtils<Ts...> kUtils;
engine::basic::TaskProcessor<kThreadsCount - 1> taskProcessor; engine::basic::TaskProcessor<kThreadsCount - 1> taskProcessor;
utempl::Tuple<std::optional<Ts>...> storage; utempl::Tuple<std::optional<typename Ts::Type>...> storage;
inline constexpr ServiceContext() : inline constexpr ServiceContext() :
taskProcessor{utempl::Wrapper<utempl::ConstexprString{kBasicTaskProcessorName}>{}, *this} taskProcessor{utempl::Wrapper<utempl::ConstexprString{kBasicTaskProcessorName}>{}, *this}
,storage{} { ,storage{} {
@ -173,26 +216,15 @@ struct ServiceContext {
}; };
template <utempl::ConstexprString name> template <utempl::ConstexprString name>
inline constexpr auto FindComponent() -> auto& { inline constexpr auto FindComponent() -> auto& {
constexpr auto I = utempl::Find(names, name); return *Get<kUtils.GetIndexByName(name)>(this->storage);
return *Get<I>(this->storage);
}; };
template <template <typename...> typename F> template <template <typename...> typename F>
constexpr auto FindComponent() -> auto& { constexpr auto FindComponent() -> auto& {
constexpr auto arr = std::to_array<bool>({F<Ts>::value...}); return *Get<kUtils.template GetFirstIndex<F>()>(this->storage);
constexpr auto I = std::ranges::find(arr, true) - arr.begin();
return *Get<I>(this->storage);
}; };
template <template <typename...> typename F> template <template <typename...> typename F>
constexpr auto FindAllComponents() { constexpr auto FindAllComponents() {
constexpr auto Indexes = [&](auto... is) { return utempl::Unpack(utempl::PackConstexprWrapper<kUtils.template GetAllIndexes<F>(), utempl::Tuple<>>(),
return utempl::TupleCat(std::array<std::size_t, 0>{}, [&]{
if constexpr(F<Ts>::value) {
return std::to_array<std::size_t>({is});
} else {
return std::array<std::size_t, 0>{};
};
}()...);} | utempl::kSeq<sizeof...(Ts)>;
return utempl::Unpack(utempl::PackConstexprWrapper<Indexes, utempl::Tuple<>>(),
[&](auto... is) -> utempl::Tuple<decltype(*Get<is>(storage))&...> { [&](auto... is) -> utempl::Tuple<decltype(*Get<is>(storage))&...> {
return {*Get<is>(storage)...}; return {*Get<is>(storage)...};
}); });
@ -203,8 +235,7 @@ struct ServiceContext {
}; };
template <typename T> template <typename T>
inline constexpr auto FindComponent() -> T& { inline constexpr auto FindComponent() -> T& {
constexpr auto I = utempl::Find<std::remove_cvref_t<T>>(utempl::kTypeList<Ts...>); return *Get<kUtils.template GetIndexByType<T>()>(this->storage);
return *Get<I>(this->storage);
}; };
}; };
@ -223,44 +254,23 @@ inline constexpr auto Use() {
template <typename...> template <typename...>
consteval auto Ignore() {}; consteval auto Ignore() {};
template <typename Current, ConstexprConfig config, typename... Ts> template <typename Current, ConstexprConfig Config, typename... Ts>
struct DependencyInfoInjector { struct DependencyInfoInjector {
static constexpr ConstexprConfig kConfig = config; static constexpr ConstexprConfig kConfig = Config;
private: static constexpr DependenciesUtils<Ts...> kUtils;
template <utempl::ConstexprString name, utempl::ConstexprString... names, typename... TTs, Options... Options>
static consteval auto FindComponentTypeImpl(ComponentConfig<names, TTs, Options>...) { template <utempl::ConstexprString name>
if constexpr(static_cast<std::string_view>(name) == kBasicTaskProcessorName) { static consteval auto FindComponentType() {
return [&] -> engine::basic::TaskProcessor<config.template Get<"threads">() - 1> { if constexpr(name == kBasicTaskProcessorName) {
return [] -> engine::basic::TaskProcessor<Config.template Get<"threads">() - 1> {
std::unreachable(); std::unreachable();
}(); }();
} else { } else {
constexpr auto I = utempl::Find(utempl::Tuple{std::string_view{names}...}, std::string_view{name}); return [] -> decltype(Get<kUtils.GetIndexByName(name)>(kUtils.kTypeList)) {
return [&] -> decltype(utempl::Get<I>(utempl::TypeList<TTs...>{})) {
std::unreachable(); std::unreachable();
}(); }();
}; };
}; };
template <template <typename...> typename F>
static consteval auto GetIndexes() {
return [](auto... is) {
return utempl::TupleCat(std::array<std::size_t, 0>{}, [&]{
if constexpr(F<typename Ts::Type>::value) {
return std::to_array<std::size_t>({is});
} else {
return std::array<std::size_t, 0>{};
};
}()...);} | utempl::kSeq<sizeof...(Ts)>;
};
public:
template <utempl::ConstexprString name>
using FindComponentType = decltype(FindComponentTypeImpl<name>(Ts{}...));
template <typename T>
static constexpr auto FindComponentName =
[]<utempl::ConstexprString... names, typename... Tss, Options... Options>
(ComponentConfig<names, Tss, Options>...) {
return Get<utempl::Find<T>(utempl::TypeList<Tss...>{})>(utempl::Tuple{names...});
}(Ts{}...);
template < template <
utempl::ConstexprString name, utempl::ConstexprString name,
@ -274,22 +284,15 @@ public:
name name
>{} >{}
> >
static auto FindComponent() -> FindComponentType<name>&; static auto FindComponent() -> decltype(FindComponentType<name>())&;
template < template <
typename T, typename T,
typename..., typename...,
std::size_t I = utempl::loopholes::Counter<Current, utempl::Wrapper<FindComponentName<T>>>(), typename R = decltype(FindComponent<Get<kUtils.template GetIndexByType<T>()>(kUtils.kNames)>())
auto = utempl::loopholes::Injector<
DependencyInfoKey<
Current,
I
>{},
FindComponentName<T>
>{}
> >
static auto FindComponent() -> T&; static auto FindComponent() -> R;
@ -300,7 +303,7 @@ public:
std::size_t I = std::ranges::find(Arr, true) - Arr.begin(), std::size_t I = std::ranges::find(Arr, true) - Arr.begin(),
typename R = decltype(FindComponent<decltype(Get<I>(utempl::TypeList<Ts...>{}))::kName>()) typename R = decltype(FindComponent<decltype(Get<I>(utempl::TypeList<Ts...>{}))::kName>())
> >
static auto FindComponent() -> decltype(Get<I>(utempl::TypeList<Ts...>{}))::Type&; static auto FindComponent() -> R;
private: private:
@ -314,7 +317,7 @@ public:
template < template <
template <typename...> typename F, template <typename...> typename F,
typename..., typename...,
typename R = decltype(utempl::Unpack(utempl::PackConstexprWrapper<GetIndexes<F>(), utempl::Tuple<>>(), typename R = decltype(utempl::Unpack(utempl::PackConstexprWrapper<kUtils.template GetAllIndexes<F>(), utempl::Tuple<>>(),
[](auto... is) -> decltype(FindAllComponentsImpl<is...>()) { [](auto... is) -> decltype(FindAllComponentsImpl<is...>()) {
std::unreachable(); std::unreachable();
})) }))
@ -336,7 +339,7 @@ public:
}; };
template <utempl::ConstexprString name> template <utempl::ConstexprString name>
static inline consteval auto Inject() { static inline consteval auto Inject() {
Ignore<decltype(Use<Current, utempl::Wrapper<name>{}, DependencyInfoInjector<Current, config, Ts...>{}>())>(); Ignore<decltype(Use<Current, utempl::Wrapper<name>{}, DependencyInfoInjector<Current, Config, Ts...>{}>())>();
}; };
}; };
@ -505,10 +508,7 @@ struct ServiceContextBuilder {
}; };
static constexpr auto GetServiceContext() { static constexpr auto GetServiceContext() {
return []<utempl::ConstexprString... names, typename... TTs, Options... Options> return ServiceContext<config, GetIndexDependencyGraph(), ComponentConfigs...>{};
(utempl::TypeList<ComponentConfig<names, TTs, Options>...>) {
return ServiceContext<config, GetIndexDependencyGraph(), utempl::Tuple{names...}, utempl::Tuple{Options...}, TTs...>{};
}(utempl::TypeList<ComponentConfigs...>{});
}; };
static constexpr auto Run() -> void { static constexpr auto Run() -> void {

View file

@ -20,6 +20,7 @@ TEST(Dependencies, Get) {
constexpr auto dependencies = cserver::ServiceContextBuilder{} constexpr auto dependencies = cserver::ServiceContextBuilder{}
.Append<SomeOtherComponent>() .Append<SomeOtherComponent>()
.Append<SomeComponent>() .Append<SomeComponent>()
.AppendConfigParam<"threads", 8>()
.Sort() .Sort()
.GetDependencyGraph(); .GetDependencyGraph();
using Need = const cserver::DependencyGraph< using Need = const cserver::DependencyGraph<