Add constexpr constructor check
This commit is contained in:
parent
6408e8f3b4
commit
5dd7fe7903
2 changed files with 71 additions and 29 deletions
|
@ -12,11 +12,11 @@ struct SeparatedComponent {};
|
||||||
template <typename... Ts>
|
template <typename... Ts>
|
||||||
struct Options : utempl::TypeList<Ts...> {};
|
struct Options : utempl::TypeList<Ts...> {};
|
||||||
|
|
||||||
template <utempl::ConstexprString name, typename T, Options Options>
|
template <utempl::ConstexprString Name, typename T, Options Options>
|
||||||
struct ComponentConfig {
|
struct ComponentConfig {
|
||||||
using Type = T;
|
using Type = T;
|
||||||
static constexpr auto kOptions = Options;
|
static constexpr auto kOptions = Options;
|
||||||
static constexpr auto kName = name;
|
static constexpr auto kName = Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
@ -121,10 +121,43 @@ struct AsyncConditionVariable {
|
||||||
bool flag;
|
bool flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Component, typename T>
|
||||||
|
struct ServiceContextForComponent {
|
||||||
|
T& context;
|
||||||
|
static constexpr auto kConfig = T::kConfig;
|
||||||
|
static constexpr auto kUtils = T::kUtils;
|
||||||
|
|
||||||
|
template <std::size_t I>
|
||||||
|
constexpr auto FindComponent() -> decltype(this->context.template FindComponent<Component, I>()) {
|
||||||
|
return this->context.template FindComponent<Component, I>();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <utempl::ConstexprString Name>
|
||||||
|
constexpr auto FindComponent() -> decltype(FindComponent<kUtils.template GetIndexByName(Name)>()) {
|
||||||
|
return this->FindComponent<kUtils.template GetIndexByName(Name)>();
|
||||||
|
};
|
||||||
|
template <template <typename...> typename F>
|
||||||
|
constexpr auto FindComponent() -> decltype(this->FindComponent<kUtils.template GetFirstIndex<F>()>()) {
|
||||||
|
return this->FindComponent<kUtils.template GetFirstIndex<F>()>();
|
||||||
|
};
|
||||||
|
template <typename TT>
|
||||||
|
constexpr auto FindComponent() -> decltype(this->FindComponent<kUtils.template GetIndexByType<TT>()>()) {
|
||||||
|
return this->FindComponent<kUtils.template GetIndexByType<TT>()>();
|
||||||
|
};
|
||||||
|
template <template <typename...> typename F>
|
||||||
|
constexpr auto FindAllComponents() {
|
||||||
|
return utempl::Unpack(utempl::PackConstexprWrapper<kUtils.template GetAllIndexes<F>(), utempl::Tuple<>>(),
|
||||||
|
[&](auto... is) -> utempl::Tuple<decltype(*Get<is>(context.storage))&...> {
|
||||||
|
return {context.template FindComponent<Component, is>()...};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <utempl::Tuple DependencyGraph, typename T>
|
template <utempl::Tuple DependencyGraph, typename T>
|
||||||
inline constexpr auto InitComponents(T& ccontext) -> void {
|
inline constexpr auto InitComponents(T& ccontext) -> void {
|
||||||
static auto& context = ccontext;
|
static auto& context = ccontext;
|
||||||
static auto& taskProcessor = context.template FindComponent<kBasicTaskProcessorName>();
|
static auto& taskProcessor = context.taskProcessor;
|
||||||
static auto& ioContext = taskProcessor.ioContext;
|
static auto& ioContext = taskProcessor.ioContext;
|
||||||
static utempl::Tuple inited = TransformDependencyGraphToTupleWithDependenciesToInitedFlagChanges<AsyncConditionVariable, DependencyGraph>(ioContext);
|
static utempl::Tuple inited = TransformDependencyGraphToTupleWithDependenciesToInitedFlagChanges<AsyncConditionVariable, DependencyGraph>(ioContext);
|
||||||
auto work = make_work_guard(ioContext);
|
auto work = make_work_guard(ioContext);
|
||||||
|
@ -134,7 +167,9 @@ 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::kUtils.kNames)>{}, context);
|
ServiceContextForComponent<decltype(Get<Is>(decltype(T::kUtils)::kComponentConfigs)), T> currentContext{context};
|
||||||
|
Get<Is>(context.storage).emplace(utempl::Wrapper<Get<Is>(T::kUtils.kNames)>{},
|
||||||
|
currentContext);
|
||||||
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();}) {
|
||||||
|
@ -206,36 +241,39 @@ struct ServiceContext {
|
||||||
engine::basic::TaskProcessor<kThreadsCount - 1> taskProcessor;
|
engine::basic::TaskProcessor<kThreadsCount - 1> taskProcessor;
|
||||||
utempl::Tuple<std::optional<typename Ts::Type>...> storage;
|
utempl::Tuple<std::optional<typename Ts::Type>...> storage;
|
||||||
|
|
||||||
inline constexpr ServiceContext() :
|
constexpr ServiceContext() :
|
||||||
taskProcessor{utempl::Wrapper<utempl::ConstexprString{kBasicTaskProcessorName}>{}, *this}
|
taskProcessor{utempl::Wrapper<utempl::ConstexprString{kBasicTaskProcessorName}>{}, *this}
|
||||||
,storage{} {
|
,storage{} {
|
||||||
};
|
};
|
||||||
inline constexpr auto Run() {
|
constexpr auto Run() {
|
||||||
impl::InitComponents<DependencyGraph>(*this);
|
impl::InitComponents<DependencyGraph>(*this);
|
||||||
this->taskProcessor.Run();
|
this->taskProcessor.Run();
|
||||||
};
|
};
|
||||||
template <utempl::ConstexprString name>
|
|
||||||
inline constexpr auto FindComponent() -> auto& {
|
|
||||||
return *Get<kUtils.GetIndexByName(name)>(this->storage);
|
template <typename Component>
|
||||||
|
constexpr auto GetContextFor() /* Internal Use Only */ {
|
||||||
|
return impl::ServiceContextForComponent<Component, std::decay_t<decltype(*this)>>{*this};
|
||||||
};
|
};
|
||||||
template <template <typename...> typename F>
|
|
||||||
constexpr auto FindComponent() -> auto& {
|
|
||||||
return *Get<kUtils.template GetFirstIndex<F>()>(this->storage);
|
template <typename Current, std::size_t I>
|
||||||
};
|
constexpr auto FindComponent() -> auto& requires (I == sizeof...(Ts) || requires{*Get<I>(this->storage);}) {
|
||||||
template <template <typename...> typename F>
|
constexpr auto Index = kUtils.GetIndexByName(Current::kName);
|
||||||
constexpr auto FindAllComponents() {
|
if constexpr(I == sizeof...(Ts)) {
|
||||||
return utempl::Unpack(utempl::PackConstexprWrapper<kUtils.template GetAllIndexes<F>(), utempl::Tuple<>>(),
|
|
||||||
[&](auto... is) -> utempl::Tuple<decltype(*Get<is>(storage))&...> {
|
|
||||||
return {*Get<is>(storage)...};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
template <>
|
|
||||||
inline constexpr auto FindComponent<kBasicTaskProcessorName>() -> auto& {
|
|
||||||
return this->taskProcessor;
|
return this->taskProcessor;
|
||||||
|
} else {
|
||||||
|
constexpr utempl::ConstexprString name = Current::kName;
|
||||||
|
constexpr Options options = Current::kOptions;
|
||||||
|
constexpr auto dependencies = Get<Index>(DependencyGraph);
|
||||||
|
static_assert((
|
||||||
|
/* Component Type */ std::ignore = utempl::kType<typename Current::Type>,
|
||||||
|
/* Component Name */ std::ignore = name,
|
||||||
|
/* Component Options */ std::ignore = options,
|
||||||
|
dependencies.size() != 0), "Constructor is not declared as constexpr");
|
||||||
|
|
||||||
|
return *Get<I>(this->storage);
|
||||||
};
|
};
|
||||||
template <typename T>
|
|
||||||
inline constexpr auto FindComponent() -> T& {
|
|
||||||
return *Get<kUtils.template GetIndexByType<T>()>(this->storage);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -495,7 +533,7 @@ struct ServiceContextBuilder {
|
||||||
static constexpr auto Run() -> void {
|
static constexpr auto Run() -> void {
|
||||||
static auto context = GetServiceContext();
|
static auto context = GetServiceContext();
|
||||||
context.Run();
|
context.Run();
|
||||||
context.template FindComponent<kBasicTaskProcessorName>().ioContext.run();
|
context.taskProcessor.ioContext.run();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // namespace cserver
|
} // namespace cserver
|
||||||
|
|
|
@ -36,7 +36,11 @@ TEST(Meta, AllDependencies) {
|
||||||
|
|
||||||
constexpr auto dependencies = builder.GetDependencyGraph();
|
constexpr auto dependencies = builder.GetDependencyGraph();
|
||||||
using Need = utempl::Tuple<OtherComponent&, OtherComponent2&>;
|
using Need = utempl::Tuple<OtherComponent&, OtherComponent2&>;
|
||||||
using R = decltype(builder.GetServiceContext().FindAllComponents<SomeM>());
|
using R = decltype(
|
||||||
|
builder
|
||||||
|
.GetServiceContext()
|
||||||
|
.GetContextFor<cserver::ComponentConfig<"some", SomeComponent, {}>>()
|
||||||
|
.FindAllComponents<SomeM>());
|
||||||
|
|
||||||
EXPECT_EQ(boost::typeindex::type_id<R>().pretty_name(),
|
EXPECT_EQ(boost::typeindex::type_id<R>().pretty_name(),
|
||||||
boost::typeindex::type_id<Need>().pretty_name());
|
boost::typeindex::type_id<Need>().pretty_name());
|
||||||
|
|
Loading…
Reference in a new issue