Skip to content

Commit

Permalink
fix warning for clang
Browse files Browse the repository at this point in the history
  • Loading branch information
oathdruid committed May 28, 2024
1 parent f4f39c8 commit b0788f2
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 133 deletions.
4 changes: 3 additions & 1 deletion src/babylon/any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ struct Any::TypeDescriptor<void> : public TypeDescriptor<void, int> {
static void destructor(void*) noexcept {}
static void deleter(void*) noexcept {}
static void copy_constructor(void*, const void*) {}
static void* copy_creater(const void*) {return nullptr;}
static void* copy_creater(const void*) {
return nullptr;
}

static constexpr Descriptor descriptor {
.type_id = TypeId<void>::ID,
Expand Down
78 changes: 50 additions & 28 deletions src/babylon/application_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ ApplicationContext::~ApplicationContext() noexcept {
clear();
}

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

int ApplicationContext::register_component(::std::unique_ptr<ComponentHolder>&& holder,
StringView name) noexcept {
int ApplicationContext::register_component(
::std::unique_ptr<ComponentHolder>&& holder, StringView name) noexcept {
if (!holder) {
BABYLON_LOG(WARNING) << "register get null ComponentHolder";
return -1;
Expand All @@ -40,12 +41,13 @@ int ApplicationContext::register_component(::std::unique_ptr<ComponentHolder>&&
auto pholder = holder.get();
_holders.emplace_back(::std::move(holder));

pholder->for_each_type([&] (const Id* type) {
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";
BABYLON_LOG(DEBUG) << "register different component of same type "
<< *type << " will disable wireup by type";
result.first->second = nullptr;
}
}
Expand All @@ -54,7 +56,9 @@ int ApplicationContext::register_component(::std::unique_ptr<ComponentHolder>&&
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";
BABYLON_LOG(WARNING)
<< "register different component of same type " << *type
<< " with same name " << name << " will disable wireup";
result.first->second = nullptr;
}
}
Expand All @@ -67,14 +71,14 @@ void ApplicationContext::clear() noexcept {
struct SeqGt {
using T = ::std::unique_ptr<ComponentHolder>;
inline bool operator()(const T& left, const T& right) const noexcept {
return left->sequence() > right->sequence();
return left->sequence() > right->sequence();
}
};
::std::sort(_holders.begin(), _holders.end(), SeqGt());
// 针对GLIBCXX,clear会按序析构
// 但是LIBCPP行为并非如此,这里主动reset确保清理顺序
for (auto& holder : _holders) {
holder.reset(nullptr);
holder.reset(nullptr);
}
_holders.clear();
_holder_by_type.clear();
Expand All @@ -85,75 +89,92 @@ void ApplicationContext::clear() noexcept {

////////////////////////////////////////////////////////////////////////////////
// ApplicationContext::ComponentHolder begin
::std::unique_ptr<void, void(*)(void*)>
ApplicationContext::ComponentHolder::create(ApplicationContext& context) noexcept {
::std::unique_ptr<void, void (*)(void*)>
ApplicationContext::ComponentHolder::create(
ApplicationContext& context) noexcept {
return create(context, _option);
}

::std::unique_ptr<void, void(*)(void*)>
ApplicationContext::ComponentHolder::create(ApplicationContext& context, const Any& option) noexcept {
::std::unique_ptr<void, void (*)(void*)>
ApplicationContext::ComponentHolder::create(ApplicationContext& context,
const Any& option) noexcept {
return create_instance(context, option).release(_type_id);
}

void ApplicationContext::ComponentHolder::for_each_type(const ::std::function<void(const Id*)>& callback) const noexcept {
void ApplicationContext::ComponentHolder::for_each_type(
const ::std::function<void(const Id*)>& callback) const noexcept {
callback(&_type_id->type_id);
for (auto& pair : _convert_offset) {
callback(pair.first);
}
}

void ApplicationContext::ComponentHolder::set_support_singleton(bool support) noexcept {
_singleton_state = support ? SingletonState::UNINITIALIZED : SingletonState::DISABLED;
void ApplicationContext::ComponentHolder::set_support_singleton(
bool support) noexcept {
_singleton_state =
support ? SingletonState::UNINITIALIZED : SingletonState::DISABLED;
}

int ApplicationContext::ComponentHolder::autowire(Any& instance, ApplicationContext& context) noexcept {
int ApplicationContext::ComponentHolder::autowire(
Any& instance, ApplicationContext& context) noexcept {
return _autowire_function(instance, context);
}

int ApplicationContext::ComponentHolder::initialize(Any& instance, ApplicationContext& context, const Any& option) noexcept {
int ApplicationContext::ComponentHolder::initialize(
Any& instance, ApplicationContext& context, const Any& option) noexcept {
return _initialize_function(instance, context, option);
}

Any ApplicationContext::ComponentHolder::create_instance(ApplicationContext& context, const Any& option) noexcept {
Any ApplicationContext::ComponentHolder::create_instance(
ApplicationContext& context, const Any& option) noexcept {
auto instance = create_instance();
if (instance) {
auto ret = autowire(instance, context);
if (ret != 0) {
BABYLON_LOG(WARNING) << "autowire failed for component of type " << _type_id->type_id;
BABYLON_LOG(WARNING) << "autowire failed for component of type "
<< _type_id->type_id;
instance.clear();
} else {
ret = initialize(instance, context, option);
if (ret != 0) {
BABYLON_LOG(WARNING) << "initialize failed for component of type " << _type_id->type_id;
BABYLON_LOG(WARNING)
<< "initialize failed for component of type " << _type_id->type_id;
instance.clear();
}
}
} else {
BABYLON_LOG(WARNING) << "create instance failed for component of type " << _type_id->type_id;
BABYLON_LOG(WARNING) << "create instance failed for component of type "
<< _type_id->type_id;
}
return instance;
}

void* ApplicationContext::ComponentHolder::create_and_then_get(ApplicationContext& context) noexcept {
void* ApplicationContext::ComponentHolder::create_and_then_get(
ApplicationContext& context) noexcept {
::std::lock_guard<std::recursive_mutex> lock(*_mutex);
if (_singleton_state == ComponentHolder::SingletonState::INITIALIZING) {
BABYLON_LOG(WARNING) << "initialize failed for recursive dependent component of type " << _type_id->type_id;
BABYLON_LOG(WARNING)
<< "initialize failed for recursive dependent component of type "
<< _type_id->type_id;
return nullptr;
}
if (_singleton_state == ComponentHolder::SingletonState::UNINITIALIZED) {
_singleton_state = ComponentHolder::SingletonState::INITIALIZING;
_singleton_state = ComponentHolder::SingletonState::INITIALIZING;
_singleton = create(context);
_sequence = next_sequence();
atomic_singleton_state().store(ComponentHolder::SingletonState::INITIALIZED, ::std::memory_order_release);
atomic_singleton_state().store(ComponentHolder::SingletonState::INITIALIZED,
::std::memory_order_release);
}
return _singleton.get();
}

ApplicationContext::EmptyComponentHolder ApplicationContext::EMPTY_COMPONENT_HOLDER;
ApplicationContext::EmptyComponentHolder
ApplicationContext::EMPTY_COMPONENT_HOLDER;

////////////////////////////////////////////////////////////////////////////////
// ApplicationContext::EmptyComponentHolder begin
ApplicationContext::EmptyComponentHolder::EmptyComponentHolder() noexcept : ComponentHolder {static_cast<void*>(nullptr)} {}
ApplicationContext::EmptyComponentHolder::EmptyComponentHolder() noexcept
: ComponentHolder {static_cast<void*>(nullptr)} {}

Any ApplicationContext::EmptyComponentHolder::create_instance() noexcept {
return {};
Expand All @@ -166,7 +187,8 @@ size_t ApplicationContext::ComponentHolder::next_sequence() noexcept {
return counter.fetch_add(1, ::std::memory_order_relaxed);
}

ptrdiff_t ApplicationContext::ComponentHolder::convert_offset(const Id* type) const noexcept {
ptrdiff_t ApplicationContext::ComponentHolder::convert_offset(
const Id* type) const noexcept {
auto iter = _convert_offset.find(type);
if (iter != _convert_offset.end()) {
return iter->second;
Expand Down
108 changes: 55 additions & 53 deletions src/babylon/application_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#include "babylon/any.h" // babylon::Any
#include "babylon/logging/interface.h" // BABYLON_LOG

#include "absl/container/flat_hash_map.h" // absl::flat_hash_map
// clang-foramt off
#include BABYLON_EXTERNAL(absl / container / flat_hash_map.h) // absl::flat_hash_map
// clang-foramt on

#include "boost/preprocessor/comparison/less.hpp" // BOOST_PP_LESS
#include "boost/preprocessor/control/if.hpp" // BOOST_PP_IF
#include "boost/preprocessor/facilities/expand.hpp" // BOOST_PP_EXPAND
Expand Down Expand Up @@ -31,10 +34,6 @@ class ApplicationContext {
template <typename T>
using ScopedComponent = ::std::unique_ptr<T, OffsetDeleter>;

// 组件的使用侧接口,提供工厂和单例两种使用模式
template <typename T>
class ComponentAccessor;

// 组件的提供侧接口,通过继承可以定制组件的初始化和组装行为
class ComponentHolder;
// 默认的组件机制DefaultComponentHolder
Expand All @@ -49,10 +48,13 @@ class ApplicationContext {
class FactoryComponentHolder;
// 内部使用,永远返回失败
class EmptyComponentHolder;

template <typename T, typename... BS>
class DefaultComponentRegister;

// 组件的使用侧接口,提供工厂和单例两种使用模式
template <typename T>
class ComponentAccessor;

// 可以默认构造,尽管大多情况下使用单例即可
// 由于存在较多记录指针的场景,禁用移动和拷贝避免误用
ApplicationContext() = default;
Expand Down Expand Up @@ -127,51 +129,6 @@ class ApplicationContext::OffsetDeleter {
ptrdiff_t offset {0};
};

template <typename T>
class ApplicationContext::ComponentAccessor {
public:
// ComponentHolder的轻量级包装
// 默认实现包装了可用且永远返回失败和nullptr
inline ComponentAccessor() noexcept = default;
inline ComponentAccessor(ComponentAccessor&&) noexcept = default;
inline ComponentAccessor(const ComponentAccessor&) noexcept = default;
inline ComponentAccessor& operator=(ComponentAccessor&&) noexcept = default;
inline ComponentAccessor& operator=(const ComponentAccessor&) noexcept =
default;
inline ~ComponentAccessor() noexcept = default;

// 作为ApplicationContext::component_accessor的返回值
// 用自身的bool转换来表达是否成功找到可用的Component
inline operator bool() const noexcept;

// 设置默认初始化选项,应用在后续组件初始化中
template <typename U>
void set_option(U&& option) noexcept;

// 按照工厂模式创建一个新的组件实例,由于组件实例可能存在非虚父类转换
// 返回携带定制销毁器的智能指针来实现正确的销毁
ScopedComponent<T> create() noexcept;
ScopedComponent<T> create(const Any& option) noexcept;

// 按照单例模式获取组件实例
inline T* get() noexcept;

// 综合组件获取接口
// 优先使用单例模式,单例模式不可用时使用工厂模式
inline ScopedComponent<T> get_or_create() noexcept;

private:
// 仅供ApplicationContext::component_accessor使用
inline ComponentAccessor(ApplicationContext& context, ComponentHolder& holder,
ptrdiff_t type_offset) noexcept;

ApplicationContext* _context {nullptr};
ComponentHolder* _holder {&EMPTY_COMPONENT_HOLDER};
ptrdiff_t _type_offset {0};

friend class ApplicationContext;
};

class ApplicationContext::ComponentHolder {
public:
// 构造时需要给定必要的类型信息,禁用默认构造
Expand Down Expand Up @@ -236,8 +193,8 @@ class ApplicationContext::ComponentHolder {
virtual Any create_instance() noexcept = 0;

private:
BABYLON_DECLARE_MEMBER_INVOCABLE(initialize, Initializeable);
BABYLON_DECLARE_MEMBER_INVOCABLE(__babylon_autowire, AutoWireable);
BABYLON_DECLARE_MEMBER_INVOCABLE(initialize, Initializeable)
BABYLON_DECLARE_MEMBER_INVOCABLE(__babylon_autowire, AutoWireable)

// 单例的状态,未初始化、初始化中、初始化完成
enum class SingletonState {
Expand Down Expand Up @@ -370,6 +327,51 @@ class ApplicationContext::DefaultComponentRegister {
DefaultComponentRegister(StringView name) noexcept;
};

template <typename T>
class ApplicationContext::ComponentAccessor {
public:
// ComponentHolder的轻量级包装
// 默认实现包装了可用且永远返回失败和nullptr
inline ComponentAccessor() noexcept = default;
inline ComponentAccessor(ComponentAccessor&&) noexcept = default;
inline ComponentAccessor(const ComponentAccessor&) noexcept = default;
inline ComponentAccessor& operator=(ComponentAccessor&&) noexcept = default;
inline ComponentAccessor& operator=(const ComponentAccessor&) noexcept =
default;
inline ~ComponentAccessor() noexcept = default;

// 作为ApplicationContext::component_accessor的返回值
// 用自身的bool转换来表达是否成功找到可用的Component
inline operator bool() const noexcept;

// 设置默认初始化选项,应用在后续组件初始化中
template <typename U>
void set_option(U&& option) noexcept;

// 按照工厂模式创建一个新的组件实例,由于组件实例可能存在非虚父类转换
// 返回携带定制销毁器的智能指针来实现正确的销毁
ScopedComponent<T> create() noexcept;
ScopedComponent<T> create(const Any& option) noexcept;

// 按照单例模式获取组件实例
inline T* get() noexcept;

// 综合组件获取接口
// 优先使用单例模式,单例模式不可用时使用工厂模式
inline ScopedComponent<T> get_or_create() noexcept;

private:
// 仅供ApplicationContext::component_accessor使用
inline ComponentAccessor(ApplicationContext& context, ComponentHolder& holder,
ptrdiff_t type_offset) noexcept;

ApplicationContext* _context {nullptr};
ComponentHolder* _holder {&EMPTY_COMPONENT_HOLDER};
ptrdiff_t _type_offset {0};

friend class ApplicationContext;
};

////////////////////////////////////////////////////////////////////////////////
// ApplicationContext::OffsetDeleter begin
inline ApplicationContext::OffsetDeleter::OffsetDeleter(
Expand Down
4 changes: 4 additions & 0 deletions test/test_any.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ struct AnyTest : public ::testing::Test {
static size_t destruct_times;

struct NormalClass {
NormalClass() = default;
NormalClass(const NormalClass&) = default;
~NormalClass() {
destruct_times++;
}
Expand All @@ -936,6 +938,8 @@ struct AnyTest : public ::testing::Test {
};

struct InplaceClass {
InplaceClass() = default;
InplaceClass(const InplaceClass&) = default;
~InplaceClass() {
destruct_times++;
}
Expand Down
Loading

0 comments on commit b0788f2

Please sign in to comment.