Skip to content

Commit

Permalink
move conflict check in ApplicationContext from auto to manual (#63)
Browse files Browse the repository at this point in the history
* move conflict check in ApplicationContext from auto to manual

* move conflict check in ApplicationContext from auto to manual
  • Loading branch information
oathdruid authored Oct 17, 2024
1 parent 1f7eca5 commit 377b09e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 79 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ jobs:
key: bazel-disk-arenastring-${{matrix.compiler.name}}-${{matrix.stdlib.name}}-${{matrix.mutable.name}}-${{github.sha}}

cpp14-coroutine:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
Expand Down
31 changes: 16 additions & 15 deletions src/babylon/application_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,45 +31,46 @@ ApplicationContext::~ApplicationContext() noexcept {
clear();
}

int ApplicationContext::register_component(
void ApplicationContext::register_component(
::std::unique_ptr<ComponentHolder>&& holder) noexcept {
return register_component(::std::move(holder), "");
}

int ApplicationContext::register_component(
void ApplicationContext::register_component(
::std::unique_ptr<ComponentHolder>&& holder, StringView name) noexcept {
if (!holder) {
BABYLON_LOG(WARNING) << "register get null ComponentHolder";
return -1;
return;
}

auto pholder = holder.get();
_holders.emplace_back(::std::move(holder));

pholder->set_name(name);
pholder->for_each_type([&](const Id* type) {
{
auto result = _holder_by_type.emplace(type, pholder);
// type冲突,设置无法只按type获取
if (result.second == false) {
BABYLON_LOG(DEBUG) << "register different component of same type "
<< *type << " will disable wireup by type";
// Find one type only accessable path
if (result.second) {
pholder->increase_accessable_path();
} else if (result.first->second) {
// Remove one type only accessable path
result.first->second->decrease_accessable_path();
result.first->second = nullptr;
}
}
if (!name.empty()) {
::std::tuple<const Id*, ::std::string> key {type, name};
auto result = _holder_by_type_and_name.emplace(key, pholder);
// type and name冲突
if (result.second == false) {
BABYLON_LOG(WARNING)
<< "register different component of same type " << *type
<< " with same name " << name << " will disable wireup";
// Find one type name accessable path
if (result.second) {
pholder->increase_accessable_path();
} else if (result.first->second) {
// Remove one type name only accessable path
result.first->second->decrease_accessable_path();
result.first->second = nullptr;
}
}
});

return 0;
}

ApplicationContext::ComponentIterator ApplicationContext::begin() noexcept {
Expand Down
50 changes: 47 additions & 3 deletions src/babylon/application_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ class ApplicationContext {
static ApplicationContext& instance() noexcept;

// 注册一个组件,可以额外附加一个名称用于区分同类型的组件
int register_component(::std::unique_ptr<ComponentHolder>&& holder) noexcept;
int register_component(::std::unique_ptr<ComponentHolder>&& holder,
StringView name) noexcept;
void register_component(::std::unique_ptr<ComponentHolder>&& holder) noexcept;
void register_component(::std::unique_ptr<ComponentHolder>&& holder,
StringView name) noexcept;

// 取得一个明确类型的组件访问器
// 在需要反复使用工厂构造组件的情况下可以节省冗余寻址成本
Expand Down Expand Up @@ -168,6 +168,12 @@ class ApplicationContext::ComponentHolder {

inline size_t sequence() const noexcept;

// How many paths exist to access this component by type or name.
// Use to detect orphan component cause by type and name conflict.
inline size_t accessable_path_number() const noexcept;

inline const ::std::string& name() const noexcept;

protected:
// 构造时需要给定必要的类型信息
// T: 应和create_instance返回实际类型一致
Expand Down Expand Up @@ -287,6 +293,12 @@ class ApplicationContext::ComponentHolder {
int>::type = 0>
static int initialize(Any&, ApplicationContext&, const Any&) noexcept;

inline void increase_accessable_path() noexcept;
inline void decrease_accessable_path() noexcept;

inline void set_name(StringView name) noexcept;

::std::string _name;
const Any::Descriptor* _type_id {Any::descriptor<void>()};
::absl::flat_hash_map<const Id*, ptrdiff_t> _convert_offset;
int (*_autowire_function)(Any&, ApplicationContext&) {nullptr};
Expand All @@ -297,6 +309,9 @@ class ApplicationContext::ComponentHolder {
SingletonState _singleton_state {SingletonState::UNINITIALIZED};
Any _singleton;
size_t _sequence {0};
size_t _accessable_path {0};

friend ApplicationContext;
};

template <typename T, typename... BS>
Expand Down Expand Up @@ -528,6 +543,8 @@ ApplicationContext::get_or_create(StringView name) noexcept {
// ApplicationContext end
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// ApplicationContext::ComponentHolder begin
template <typename T, typename... BS>
ABSL_ATTRIBUTE_NOINLINE ApplicationContext::ComponentHolder::ComponentHolder(
T*, BS*...) noexcept {
Expand Down Expand Up @@ -570,6 +587,16 @@ ApplicationContext::ComponentHolder::sequence() const noexcept {
return _sequence;
}

inline ABSL_ATTRIBUTE_ALWAYS_INLINE size_t
ApplicationContext::ComponentHolder::accessable_path_number() const noexcept {
return _accessable_path;
}

inline ABSL_ATTRIBUTE_ALWAYS_INLINE const ::std::string&
ApplicationContext::ComponentHolder::name() const noexcept {
return _name;
}

template <typename T>
ABSL_ATTRIBUTE_NOINLINE void
ApplicationContext::ComponentHolder::set_type() noexcept {
Expand Down Expand Up @@ -683,6 +710,23 @@ ABSL_ATTRIBUTE_NOINLINE int ApplicationContext::ComponentHolder::initialize(
return 0;
}

inline void
ApplicationContext::ComponentHolder::increase_accessable_path() noexcept {
_accessable_path++;
}

inline void
ApplicationContext::ComponentHolder::decrease_accessable_path() noexcept {
_accessable_path--;
}

inline void ApplicationContext::ComponentHolder::set_name(
StringView name) noexcept {
_name = name;
}
// ApplicationContext::ComponentHolder end
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// ApplicationContext::ComponentAccessor begin
template <typename T>
Expand Down
3 changes: 1 addition & 2 deletions src/babylon/coroutine/cancelable.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,7 @@ template <typename P>
inline ::std::coroutine_handle<> Cancellable<A>::await_suspend(
::std::coroutine_handle<P> handle) noexcept {
auto id = emplace(handle);
_task = [](A awaitable,
VersionedValue<uint32_t> id) -> Task<ResultType> {
_task = [](A awaitable, VersionedValue<uint32_t> id) -> Task<ResultType> {
struct S {
inline ~S() noexcept {
resume(id);
Expand Down
Loading

0 comments on commit 377b09e

Please sign in to comment.