From 87265d18377a67cce61e518f4178161e2ec249bf Mon Sep 17 00:00:00 2001 From: Cora <17833654450@163.com> Date: Wed, 5 Aug 2026 23:11:09 +0800 Subject: [PATCH 1/2] add Object::class_raw_name --- include/gkit/core/object.hpp | 1 + src/core/object.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/gkit/core/object.hpp b/include/gkit/core/object.hpp index 87ec03e..779da38 100644 --- a/include/gkit/core/object.hpp +++ b/include/gkit/core/object.hpp @@ -39,5 +39,6 @@ namespace gkit::core { static auto create(Args&&...) noexcept -> UniqueObject; */ virtual auto class_name() const -> std::string final; + virtual constexpr auto class_raw_name() const -> const char* final; }; } // namespace gkit::core \ No newline at end of file diff --git a/src/core/object.cpp b/src/core/object.cpp index cc73152..91a609a 100644 --- a/src/core/object.cpp +++ b/src/core/object.cpp @@ -14,4 +14,8 @@ namespace gkit::core { auto class_info = reflect::ClassDB::instance().find_with_raw(raw_name); return class_info->class_name; } + + constexpr auto Object::class_raw_name() const -> const char* { + return typeid(*this).name(); + } } // namespace gkit::core From da54d202dbfc57a2bb3043e39b57451fcdb93db1 Mon Sep 17 00:00:00 2001 From: Cora <17833654450@163.com> Date: Thu, 6 Aug 2026 15:12:36 +0800 Subject: [PATCH 2/2] - add `core::templates::GenId` for template of Id with generation - refactor `core::ObjectId` with core::templates::GenId --- include/gkit/core/object.hpp | 4 +- include/gkit/core/object_id.hpp | 73 ++-------------- include/gkit/core/templates/gen_id.hpp | 114 +++++++++++++++++++++++++ src/core/CMakeLists.txt | 1 - src/core/object.cpp | 4 - src/core/object_id.cpp | 60 ------------- src/core/object_pool.cpp | 2 +- src/core/object_pool.hpp | 4 +- 8 files changed, 125 insertions(+), 137 deletions(-) create mode 100644 include/gkit/core/templates/gen_id.hpp delete mode 100644 src/core/object_id.cpp diff --git a/include/gkit/core/object.hpp b/include/gkit/core/object.hpp index 779da38..8409924 100644 --- a/include/gkit/core/object.hpp +++ b/include/gkit/core/object.hpp @@ -39,6 +39,8 @@ namespace gkit::core { static auto create(Args&&...) noexcept -> UniqueObject; */ virtual auto class_name() const -> std::string final; - virtual constexpr auto class_raw_name() const -> const char* final; + inline virtual auto class_raw_name() const -> const char* final { + return typeid(*this).name(); + } }; } // namespace gkit::core \ No newline at end of file diff --git a/include/gkit/core/object_id.hpp b/include/gkit/core/object_id.hpp index 6e709e9..bf1d578 100644 --- a/include/gkit/core/object_id.hpp +++ b/include/gkit/core/object_id.hpp @@ -1,72 +1,9 @@ #pragma once -#include "gkit/core/templates/singleton.hpp" - -#include -#include -#include -#include -#include -#include +#include "gkit/core/object_id.hpp" +#include "gkit/core/templates/gen_id.hpp" namespace gkit::core { - class ObjectIdAllocator; - - class ObjectId final { - friend ObjectIdAllocator; - friend std::hash; - // defalut is invalid value - uint32_t id = 0u; - uint32_t version = 0u; - - public: - ObjectId() noexcept; - - public: - ObjectId(const ObjectId& other) noexcept = default; - ObjectId(ObjectId&& other) noexcept; - auto operator=(const ObjectId& other) -> ObjectId& = default; - auto operator=(ObjectId&& other) -> ObjectId& = default; - - auto operator==(const ObjectId& other) const -> bool { - return this->id == other.id && this->version == other.version; - } - - /** - * @brief check ObjectId is invalid - * @return bool - Both id and version are not zero. - */ - inline auto available() const -> bool { return this->id != 0 && this->version != 0; } - }; // class ObjectId - - class ObjectIdAllocator final : public gkit::core::templates::Singleton { - friend gkit::core::templates::Singleton; - std::mutex id_alloc_lock{}; - std::stack id_pool{}; - std::unordered_map id_version{}; - - ObjectIdAllocator() noexcept; - ~ObjectIdAllocator() = default; - - public: - /** - * @brief alloc a new ObjectId instance - * @return ObjectId - */ - auto new_one() noexcept -> ObjectId; - - /** - * @brief drop an ObjectId and recycle its id - * @param obj_id - which ObjectId is needed to be dropped - */ - auto drop(const ObjectId& obj_id) noexcept -> void; - }; // class ObjectIdAllocator -} // namespace gkit::core - -template<> -struct std::hash { - auto operator()(const gkit::core::ObjectId& objid) const -> std::size_t { - auto uint_hash = std::hash(); - return uint_hash(objid.id) ^ uint_hash(objid.version); - } -}; \ No newline at end of file + class ObjectIdTag; + using ObjectId = templates::GenId; +} // namespace gkit::core \ No newline at end of file diff --git a/include/gkit/core/templates/gen_id.hpp b/include/gkit/core/templates/gen_id.hpp new file mode 100644 index 0000000..24d1f29 --- /dev/null +++ b/include/gkit/core/templates/gen_id.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include "singleton.hpp" + +#include +#include +#include +#include +#include + +namespace gkit::core::templates { + template + class GenId { + std::uint32_t id = 0u; + std::uint32_t gen = 0u; + + public: + class IdAllocator; + + GenId() = default; + virtual ~GenId() = default; + GenId(const GenId& other) : id(other.id), gen(other.gen) {} + GenId(GenId&& other) noexcept : id(other.id), gen(other.gen) { + other.id = 0u; + other.gen = 0u; + } + + auto operator=(const GenId&) -> GenId& = default; + auto operator=(GenId&& other) noexcept -> GenId& { + if (this != &other) { + this->id = other.id; + this->gen = other.gen; + other.id = 0u; + other.gen = 0u; + } + + return *this; + }; + + inline auto operator==(const GenId& other) const -> bool { + return this->id == other.id && this->gen == other.gen; + } + + /** + * @brief check ObjectId is invalid + * @return bool - Both id and version are not zero. + */ + inline auto available() const -> bool { return this->id != 0 && this->gen != 0; } + inline auto properties() const -> std::pair { return {this->id, this->gen}; } + }; // class GenId + + template + class GenId::IdAllocator : public Singleton::IdAllocator> { + friend Singleton::IdAllocator>; + std::mutex alloc_mutex{}; + std::stack id_pool{{1}}; + std::unordered_map id_gen_map{}; + + IdAllocator() noexcept = default; + ~IdAllocator() noexcept = default; + + public: + auto new_one() -> GenId; + auto drop(const GenId& dropped_id) -> void; + }; // class GenId::IdAllocator + + template + auto GenId::IdAllocator::new_one() -> GenId { + auto new_id = GenId(); + { + std::unique_lock alloc_locker(this->alloc_mutex); + if (this->id_pool.size() <= 1) { + // Final element in id_pool is not alloc before be called top(). + // So the version of final element always is one. + new_id.id = id_pool.top()++; + new_id.gen = 1; + } else { + // version of recycle id is not always one + // and is recorded to gen map when the id is dropped. + new_id.id = id_pool.top(); + id_pool.pop(); + new_id.gen = ++this->id_gen_map[new_id.id]; + } + } + + return new_id; + } + + template + auto GenId::IdAllocator::drop(const GenId& dropped_id) -> void { + auto old_id = dropped_id.id; + auto old_version = dropped_id.gen; + + { + std::unique_lock alloc_locker(this->alloc_mutex); + this->id_pool.push(old_id); + auto version_it = this->id_gen_map.find(old_id); + + // no record version ever + if (version_it == this->id_gen_map.end()) { + this->id_gen_map[old_id] = 1; + } + } + } +} // namespace gkit::core::templates + +template +struct std::hash> { + auto operator()(const gkit::core::templates::GenId& obj_id) const -> std::size_t { + auto uint_hash = std::hash(); + auto [id, version] = obj_id.properties(); + return uint_hash(id) ^ uint_hash(version); + } +}; \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 40867c1..c46acdb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -15,7 +15,6 @@ set (CORE_SRC "./reflect/serdebase.cpp" "./log.cpp" - "./object_id.cpp" "./object_pool.cpp" "./object.cpp" "./processer.cpp" diff --git a/src/core/object.cpp b/src/core/object.cpp index 91a609a..cc73152 100644 --- a/src/core/object.cpp +++ b/src/core/object.cpp @@ -14,8 +14,4 @@ namespace gkit::core { auto class_info = reflect::ClassDB::instance().find_with_raw(raw_name); return class_info->class_name; } - - constexpr auto Object::class_raw_name() const -> const char* { - return typeid(*this).name(); - } } // namespace gkit::core diff --git a/src/core/object_id.cpp b/src/core/object_id.cpp deleted file mode 100644 index ea5af7f..0000000 --- a/src/core/object_id.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "gkit/core/object_id.hpp" - -#include - -namespace gkit::core { - - /** - * ObjectId - */ - ObjectId::ObjectId() noexcept {} - ObjectId::ObjectId(ObjectId&& other) noexcept : id(other.id), version(other.version) { - other.id = 0; - other.version = 0; - } - - /** - * ObjectIdAllocator - */ - ObjectIdAllocator::ObjectIdAllocator() noexcept { - // init value, every id is alloc from 1 - // id equal zero means not alloc or invalid - this->id_pool.push(1); - } - - auto ObjectIdAllocator::new_one() noexcept -> ObjectId { - auto obj_id = ObjectId(); - { - std::unique_lock alloc_locker(this->id_alloc_lock); - if (this->id_pool.size() <= 1) { - // Final element in id_pool is not alloc before be called top(). - // So the version of final element always is one. - obj_id.id = id_pool.top()++; - obj_id.version = 1; - } else { - // version of recycle id is not always one - // and is recorded to version map when the id is dropped. - obj_id.id = id_pool.top(); - id_pool.pop(); - obj_id.version = ++this->id_version[obj_id.id]; - } - } - return obj_id; - } - - auto ObjectIdAllocator::drop(const ObjectId& obj_id) noexcept -> void { - auto old_id = obj_id.id; - auto old_version = obj_id.version; - - { - std::unique_lock alloc_locker(this->id_alloc_lock); - this->id_pool.push(old_id); - auto version_it = this->id_version.find(old_id); - - // no record version ever - if (version_it == this->id_version.end()) { - this->id_version[old_id] = 1; - } - } - } -} // namespace gkit::core \ No newline at end of file diff --git a/src/core/object_pool.cpp b/src/core/object_pool.cpp index 8ff736b..ab209a9 100644 --- a/src/core/object_pool.cpp +++ b/src/core/object_pool.cpp @@ -14,7 +14,7 @@ namespace gkit::core { this->id_instance_map.erase(target_it); delete drop_obj; - auto& id_alloc = ObjectIdAllocator::instance(); + auto& id_alloc = ObjectId::IdAllocator::instance(); id_alloc.drop(drop_id); } diff --git a/src/core/object_pool.hpp b/src/core/object_pool.hpp index 54815ea..23ab2d5 100644 --- a/src/core/object_pool.hpp +++ b/src/core/object_pool.hpp @@ -27,9 +27,9 @@ namespace gkit::core { auto ObjectPool::create(Args&&... args) noexcept -> std::optional> { try { auto* obj_ptr = new T(std::forward(args)...); - auto obj_id = ObjectIdAllocator::instance().new_one(); + auto obj_id = ObjectId::IdAllocator::instance().new_one(); this->id_instance_map.emplace(obj_id, obj_ptr); - return std::make_pair(std::move(obj_id), std::move(obj_ptr)); + return std::make_pair(obj_id, obj_ptr); } catch (...) { return std::nullopt; }