Add options to component system
This commit is contained in:
parent
773b393d96
commit
587f8b25db
5 changed files with 49 additions and 38 deletions
|
@ -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 {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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(;;) {
|
||||||
|
|
Loading…
Reference in a new issue