Add options to component system

This commit is contained in:
sha512sum 2024-03-19 16:04:26 +00:00
parent 773b393d96
commit 587f8b25db
5 changed files with 49 additions and 38 deletions

View file

@ -34,11 +34,11 @@ struct HttpClient {
ctx(boost::asio::ssl::context::method::sslv23_client), ctx(boost::asio::ssl::context::method::sslv23_client),
resolver(this->taskProcessor.ioContext) {} resolver(this->taskProcessor.ioContext) {}
template <utempl::ConstexprString name, typename T> template <utempl::ConstexprString name, Options Options, typename T>
static consteval auto Adder(const T& context) { static consteval auto Adder(const T& context) {
using Type = std::remove_cvref_t<decltype(context.template FindComponent<"basicTaskProcessor">())>; using Type = std::remove_cvref_t<decltype(context.template FindComponent<"basicTaskProcessor">())>;
return context.TransformComponents( return context.TransformComponents(
[&](const ComponentConfig<name, HttpClient<>>&) -> ComponentConfig<name, HttpClient<Type>> { [&](const ComponentConfig<name, HttpClient<>, Options>&) -> ComponentConfig<name, HttpClient<Type>, Options> {
return {}; return {};
}); });
}; };

View file

@ -15,11 +15,11 @@ struct TaskProcessor {
pool{} { pool{} {
}; };
template <utempl::ConstexprString name, typename T> template <utempl::ConstexprString name, Options Options, typename T>
static consteval auto Adder(const T& context) { static consteval auto Adder(const T& context) {
constexpr std::size_t Count = T::kConfig.template Get<name>().template Get<"threadPoolSize">(); constexpr std::size_t Count = T::kConfig.template Get<name>().template Get<"threadPoolSize">();
return context.TransformComponents( return context.TransformComponents(
[&](const ComponentConfig<name, TaskProcessor<>>&) -> ComponentConfig<name, TaskProcessor<Count>> { [&](const ComponentConfig<name, TaskProcessor<>, Options>&) -> ComponentConfig<name, TaskProcessor<Count>, Options> {
return {}; return {};
}); });
}; };

View file

@ -3,14 +3,30 @@
#include <thread> #include <thread>
namespace cserver { namespace cserver {
struct SeparatedComponent {};
template <typename... Ts>
using Options = utempl::TypeList<Ts...>;
template <utempl::ConstexprString name, typename T, Options Options>
struct ComponentConfig {};
namespace impl {
template <utempl::ConstexprString name, typename T> template <utempl::ConstexprString name, typename T>
struct NamedValue { struct NamedValue {
T value; T value;
}; };
template <utempl::ConstexprString name, typename T> template <typename T>
struct ComponentConfig {}; using GetTypeFromComponentConfig = decltype(
[]<utempl::ConstexprString name, typename TT, Options Options>(const ComponentConfig<name, TT, Options>&) -> TT {
}(std::declval<T>()));
template <typename T>
inline constexpr utempl::ConstexprString kNameFromComponentConfig =
decltype([]<utempl::ConstexprString name, typename TT, Options Options>(const ComponentConfig<name, TT, Options>&) {
return utempl::Wrapper<name>{};
}(std::declval<T>()))::kValue;
template <typename T> template <typename T>
inline constexpr auto TransformIfOk(T&& value, auto&& f) { inline constexpr auto TransformIfOk(T&& value, auto&& f) {
@ -22,12 +38,14 @@ inline constexpr auto TransformIfOk(T&& value, auto&& f) {
}; };
} // namespace impl
template <typename... Ts> template <typename... Ts>
struct ConstexprConfig { struct ConstexprConfig {
utempl::Tuple<Ts...> data; utempl::Tuple<Ts...> data;
template <utempl::ConstexprString Key> template <utempl::ConstexprString Key>
inline constexpr auto Get() const -> auto { inline constexpr auto Get() const -> auto {
return [&]<typename... TTs, utempl::ConstexprString... names>(const ConstexprConfig<NamedValue<names, TTs>...>&){ return [&]<typename... TTs, utempl::ConstexprString... names>(const ConstexprConfig<impl::NamedValue<names, TTs>...>&){
constexpr auto list = utempl::TypeList<utempl::Wrapper<names>...>{}; constexpr auto list = utempl::TypeList<utempl::Wrapper<names>...>{};
constexpr std::size_t I = Find<utempl::Wrapper<Key>>(list); constexpr std::size_t I = Find<utempl::Wrapper<Key>>(list);
if constexpr(I < sizeof...(Ts)) { if constexpr(I < sizeof...(Ts)) {
@ -36,22 +54,23 @@ struct ConstexprConfig {
}(*this); }(*this);
}; };
template <utempl::ConstexprString Key, typename T> template <utempl::ConstexprString Key, typename T>
inline constexpr auto Append(T&& value) const -> ConstexprConfig<Ts..., NamedValue<Key, std::remove_cvref_t<T>>> { inline constexpr auto Append(T&& value) const -> ConstexprConfig<Ts..., impl::NamedValue<Key, std::remove_cvref_t<T>>> {
return {.data = TupleCat(this->data, utempl::MakeTuple(NamedValue<Key, std::remove_cvref_t<T>>{std::forward<T>(value)}))}; return {.data = TupleCat(this->data, utempl::MakeTuple(impl::NamedValue<Key, std::remove_cvref_t<T>>{std::forward<T>(value)}))};
}; };
}; };
template <ConstexprConfig config, auto names, typename... Ts> template <ConstexprConfig config, auto names, auto Options, typename... Ts>
struct ServiceContext { struct ServiceContext {
utempl::Tuple<Ts...> storage;
static constexpr auto kConfig = config; static constexpr auto kConfig = config;
static constexpr auto kList = utempl::TypeList<Ts...>{}; static constexpr auto kList = utempl::TypeList<Ts...>{};
static constexpr auto kThreadsCount = config.template Get<"threads">();
utempl::Tuple<Ts...> storage;
inline constexpr ServiceContext() : inline constexpr ServiceContext() :
storage{ storage{
[&]<auto... Is>(std::index_sequence<Is...>) -> utempl::Tuple<Ts...> { [&]<auto... Is>(std::index_sequence<Is...>) -> utempl::Tuple<Ts...> {
return {[&]<auto I>(utempl::Wrapper<I>) { return {[&]<auto I>(utempl::Wrapper<I>) {
return [&]() -> std::remove_cvref_t<decltype(Get<I>(storage))> { return [&]() -> std::remove_cvref_t<decltype(Get<I>(storage))> {
return {decltype(Get<I>(names)){}, *this}; return {utempl::Wrapper<Get<I>(names)>{}, *this};
}; };
}(utempl::Wrapper<Is>{})...}; }(utempl::Wrapper<Is>{})...};
}(std::index_sequence_for<Ts...>()) }(std::index_sequence_for<Ts...>())
@ -67,7 +86,7 @@ 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<utempl::Wrapper<name>>(names); constexpr auto I = utempl::Find(names, name);
return Get<I>(this->storage); return Get<I>(this->storage);
}; };
template <typename T> template <typename T>
@ -84,14 +103,14 @@ template <ConstexprConfig config = {}, typename... Ts>
struct ServiceContextBuilder { struct ServiceContextBuilder {
static constexpr auto kList = utempl::kTypeList<Ts...>; static constexpr auto kList = utempl::kTypeList<Ts...>;
static constexpr auto kConfig = config; static constexpr auto kConfig = config;
template <typename T, utempl::ConstexprString name = T::kName> template <typename T, utempl::ConstexprString name = T::kName, typename... Os>
static consteval auto Append() -> decltype(T::template Adder<name>(ServiceContextBuilder<config, Ts..., ComponentConfig<name, T>>{})) { static consteval auto Append(Options<Os...> = {}) -> decltype(T::template Adder<name, Options<Os...>{}>(ServiceContextBuilder<config, Ts..., ComponentConfig<name, T, Options<Os...>{}>>{})) {
return {}; return {};
}; };
template <typename T, utempl::ConstexprString name = T::kName> template <typename T, utempl::ConstexprString name = T::kName, typename... Os>
static consteval auto Append() -> ServiceContextBuilder<config, Ts..., ComponentConfig<name, T>> static consteval auto Append(Options<Os...> = {}) -> ServiceContextBuilder<config, Ts..., ComponentConfig<name, T, Options<Os...>{}>>
requires (!requires(ServiceContextBuilder<config, Ts..., ComponentConfig<name, T>> builder) {T::template Adder<name>(builder);}) { requires (!requires(ServiceContextBuilder<config, Ts..., ComponentConfig<name, T, Options<Os...>{}>> builder) {T::template Adder<name, Options<Os...>{}>(builder);}) {
return {}; return {};
}; };
@ -102,13 +121,13 @@ struct ServiceContextBuilder {
}; };
template <typename F> template <typename F>
static consteval auto TransformComponents(F&& f) -> ServiceContextBuilder<config, decltype(TransformIfOk(Ts{}, f))...> { static consteval auto TransformComponents(F&& f) -> ServiceContextBuilder<config, decltype(impl::TransformIfOk(Ts{}, f))...> {
return {}; return {};
}; };
template <utempl::ConstexprString name> template <utempl::ConstexprString name>
static consteval auto FindComponent() { static consteval auto FindComponent() {
return []<typename... TTs, utempl::ConstexprString... names> return []<typename... TTs, utempl::ConstexprString... names, Options... Options>
(const ServiceContextBuilder<config,ComponentConfig<names, TTs>...>&) (const ServiceContextBuilder<config, ComponentConfig<names, TTs, Options>...>&)
-> decltype(utempl::Get<Find<utempl::Wrapper<name>>(utempl::TypeList<utempl::Wrapper<names>...>{})>(utempl::TypeList<TTs...>{})) { -> decltype(utempl::Get<Find<utempl::Wrapper<name>>(utempl::TypeList<utempl::Wrapper<names>...>{})>(utempl::TypeList<TTs...>{})) {
std::unreachable(); std::unreachable();
}(ServiceContextBuilder<config, Ts...>{}); }(ServiceContextBuilder<config, Ts...>{});
@ -119,8 +138,9 @@ struct ServiceContextBuilder {
}; };
static constexpr auto Run() -> void { static constexpr auto Run() -> void {
[]<utempl::ConstexprString... names, typename... TTs>(utempl::TypeList<ComponentConfig<names, TTs>...>) { []<utempl::ConstexprString... names, typename... TTs, Options... Options>
ServiceContext<config, utempl::kTypeList<utempl::Wrapper<names>...>, TTs...> context; (utempl::TypeList<ComponentConfig<names, TTs, Options>...>) {
ServiceContext<config, utempl::Tuple{names...}, utempl::Tuple{Options...}, TTs...> context;
context.Run(); context.Run();
for(;;) { for(;;) {
std::this_thread::sleep_for(std::chrono::minutes(1)); std::this_thread::sleep_for(std::chrono::minutes(1));

View file

@ -8,10 +8,10 @@
namespace cserver::server::handlers { namespace cserver::server::handlers {
struct HTTPHandlerBase { struct HTTPHandlerBase {
template <typename T, utempl::ConstexprString name> template <typename T, utempl::ConstexprString name, Options Options>
static consteval auto Adder(const auto& context) { static consteval auto Adder(const auto& context) {
return context.TransformComponents([]<typename TT>(const ComponentConfig<T::kHandlerManagerName, TT>) { return context.TransformComponents([]<typename TT>(const ComponentConfig<T::kHandlerManagerName, TT, Options>) {
return ComponentConfig<T::kHandlerManagerName, typename TT::template AddHandler<ComponentConfig<name, T>>>{}; return ComponentConfig<T::kHandlerManagerName, typename TT::template AddHandler<ComponentConfig<name, T, Options>>, Options>{};
}); });
}; };
template <typename Self> template <typename Self>

View file

@ -8,16 +8,7 @@
namespace cserver::server::server { namespace cserver::server::server {
namespace impl {
template <typename T>
using GetTypeFromComponentConfig = decltype([]<utempl::ConstexprString name, typename TT>(const ComponentConfig<name, TT>&) -> TT {}(std::declval<T>()));
template <typename T>
inline constexpr utempl::ConstexprString kNameFromComponentConfig =
decltype([]<utempl::ConstexprString name, typename TT>(const ComponentConfig<name, TT>&) {
return utempl::Wrapper<name>{};
} (std::declval<T>()))::kValue;
} // namespace impl
template <utempl::ConstexprString TPName = "basicTaskProcessor", typename TaskProcessor = int, typename... Ts> template <utempl::ConstexprString TPName = "basicTaskProcessor", typename TaskProcessor = int, typename... Ts>
struct Server { struct Server {
@ -27,7 +18,7 @@ struct Server {
unsigned short port; unsigned short port;
static constexpr utempl::Tuple kNames = {impl::kNameFromComponentConfig<Ts>...}; static constexpr utempl::Tuple kNames = {impl::kNameFromComponentConfig<Ts>...};
static constexpr utempl::Tuple kPaths = {impl::GetTypeFromComponentConfig<Ts>::kPath...}; static constexpr utempl::Tuple kPaths = {impl::GetTypeFromComponentConfig<Ts>::kPath...};
template <utempl::ConstexprString name, typename T> template <utempl::ConstexprString name, Options Options, typename T>
static consteval auto Adder(const T& context) { static consteval auto Adder(const T& context) {
constexpr utempl::ConstexprString tpName = [&]{ constexpr utempl::ConstexprString tpName = [&]{
if constexpr(requires{T::kConfig.template Get<name>().template Get<"taskProcessor">();}) { if constexpr(requires{T::kConfig.template Get<name>().template Get<"taskProcessor">();}) {
@ -38,7 +29,7 @@ struct Server {
}(); }();
using TP = decltype(context.template FindComponent<tpName>()); using TP = decltype(context.template FindComponent<tpName>());
return context.TransformComponents( return context.TransformComponents(
[&](const ComponentConfig<name, Server<TPName, int, Ts...>>&) -> ComponentConfig<name, Server<tpName, TP, Ts...>> { [&](const ComponentConfig<name, Server<TPName, int, Ts...>, Options>&) -> ComponentConfig<name, Server<tpName, TP, Ts...>, Options> {
return {}; return {};
}); });
}; };
@ -88,7 +79,7 @@ struct Server {
co_await boost::asio::async_write(socket, boost::asio::buffer(error404.data(), error404.size()), boost::asio::use_awaitable); co_await boost::asio::async_write(socket, boost::asio::buffer(error404.data(), error404.size()), boost::asio::use_awaitable);
}; };
}; };
auto Task() -> cserver::Task<void> { auto Task() -> Task<void> {
auto executor = co_await boost::asio::this_coro::executor; auto executor = co_await boost::asio::this_coro::executor;
boost::asio::ip::tcp::acceptor acceptor{executor, {boost::asio::ip::tcp::v6(), this->port}}; boost::asio::ip::tcp::acceptor acceptor{executor, {boost::asio::ip::tcp::v6(), this->port}};
for(;;) { for(;;) {