From 3fd47f6bfe78d104053d70911cdc42b9267a9768 Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Thu, 11 Sep 2025 22:01:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=86=85=E5=AD=98=E6=B1=A0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ECSMemoryPool/ecs_memorypool.h | 102 ++++++++++++++++++++++++++++++--- ECSMemoryPool/memory_pages.cpp | 52 +++++++++++------ ECSMemoryPool/memory_pages.h | 40 +++++++++---- 3 files changed, 160 insertions(+), 34 deletions(-) diff --git a/ECSMemoryPool/ecs_memorypool.h b/ECSMemoryPool/ecs_memorypool.h index d32181c..0c0762a 100644 --- a/ECSMemoryPool/ecs_memorypool.h +++ b/ECSMemoryPool/ecs_memorypool.h @@ -7,22 +7,110 @@ #include template -concept CompenentType = requires(T t, const QJsonObject &in, QJsonObject out){ - { T::typeCode() } -> std::same_as; - { T::typeSize() } -> std::same_as; +concept CompenentType = requires(T t, T other, const QJsonObject & in, QJsonObject & out) { + { T::typeCode() } -> std::same_as; + { T::typeSize() } -> std::same_as; { t.loadFrom(in) } -> std::same_as; { t.saveTo(out) } -> std::same_as; }; +/// +/// 组件引用符号 +/// +/// +template class ComponentRefer : protected MemoryElement { +public: + ComponentRefer(ElementControlBlock* data) : MemoryElement(data) { referAdd(); } + virtual ~ComponentRefer() { referSub(); } -class ECSMEMORYPOOL_EXPORT ECSMemoryPool{ + T* dataLock() { + return (T*)(MemoryElement::dataLock()); + } + void unlock() { + MemoryElement::release(); + } +}; + + +class ECSMEMORYPOOL_EXPORT ECSMemoryPool { private: - QList> _storage_pages; + std::mutex _pool_protected_; + + /// + /// 携带默认参数数据元素组件内存实例 + /// + QHash> _basic_component_memory_example; + /// + /// map 内存页存储 + /// + QMultiHash _storage_pages; public: ECSMemoryPool(); - template void registerComponent() { + /// + /// 注册携带默认参数的数据组件 + /// + /// + /// + template void registerComponent(T one) { + std::lock_guard lockx(_pool_protected_); - } + auto ptr = new char[T::typeSize()]; + memcpy(ptr, &one, T::typeSize()); + + // 注册组件数据类型 + auto type_code = T::typeCode(); + auto type_size = T::typeSize(); + _basic_component_memory_example[type_code] = std::make_pair(type_size, ptr); + } + + /// + /// 创建一个新的数据组件 + /// + /// + /// + template ComponentRefer generate() { + std::lock_guard lockx(_pool_protected_); + + auto type_code = T::typeCode(); + ElementControlBlock* refer_ptr = nullptr; + // 获取指定类型关联的内存页 + QList page_list = _storage_pages.values(type_code); + + // 迭代内存页集合 + for (auto page_ptr : page_list) { + auto max_element_cnt = page_ptr->maxSliceCount(); + auto active_cnt = page_ptr->getActiveCount(); + // 初级校核可用数量 + if (active_cnt < max_element_cnt) { + // 逐个查找数据元素 + for (auto eidx = 0; eidx < max_element_cnt; eidx++) { + auto slice_ptr = page_ptr->getSlicePtr(eidx); + // 访问排他 + slice_ptr->page_refer->lock(); + // 裁决元素可用性 + if (!slice_ptr->refer_count) { + // 元素可用 + slice_ptr->refer_count++; + refer_ptr = slice_ptr; + slice_ptr->page_refer->release(); + // 跳转到元素重用 + goto exists_reuse; + } + else { + slice_ptr->page_refer->release(); + } + } + } + } + + // 生成新的内存页 + auto new_page = new MemoryPage(MemoryElement::rawSize(T::typeSize()), type_code); + _storage_pages->insert(type_code, new_page); + refer_ptr = new_page->getSlicePtr(0); + + exists_reuse: + return ComponentRefer(refer_ptr); + } }; diff --git a/ECSMemoryPool/memory_pages.cpp b/ECSMemoryPool/memory_pages.cpp index 436cf80..4a31212 100644 --- a/ECSMemoryPool/memory_pages.cpp +++ b/ECSMemoryPool/memory_pages.cpp @@ -7,6 +7,19 @@ MemoryPage::MemoryPage(uint16_t element_size, uint64_t typecode) pcb.typecode_of_element = typecode; } +uint16_t MemoryPage::dataSliceSize() const +{ + return pcb.byte_count_per_element - MemoryElement::data_buffer_offset; +} + +uint16_t MemoryPage::getActiveCount(uint16_t inc) const +{ + auto data_ptr = const_cast(this); + std::lock_guard g(data_ptr->pcb.access_protected); + data_ptr->pcb.active_elements_count += inc; + return data_ptr->pcb.active_elements_count; +} + void MemoryPage::accessRecord(uint64_t timepoint_usec) { std::lock_guard g(pcb.access_protected); pcb.curr_access_usec = timepoint_usec; @@ -26,9 +39,9 @@ std::pair MemoryPage::getRecords() const { return std::make_pair(pcb.curr_access_usec, pcb.acc_count_per_cycle); } -ElementControlBlock* MemoryPage::getElementPtr(int index) { - auto member_cnt = elementCount(); - auto element_size = elementSize(); +ElementControlBlock* MemoryPage::getSlicePtr(int index) { + auto member_cnt = maxSliceCount(); + auto element_size = sliceRawSize(); ElementControlBlock* element_ptr = nullptr; if (index >= 0 && index < member_cnt) { @@ -66,19 +79,19 @@ uint64_t MemoryPage::elementTypeCode() const return pcb.typecode_of_element; } -uint16_t MemoryPage::elementSize() const { +uint16_t MemoryPage::sliceRawSize() const { auto data_ptr = const_cast(this); std::lock_guard g(data_ptr->pcb.access_protected); return pcb.byte_count_per_element; } -uint16_t MemoryPage::elementCount() const { +uint16_t MemoryPage::maxSliceCount() const { uint16_t cnt = sizeof(data_buffer); - return cnt / this->elementSize(); + return cnt / this->sliceRawSize(); } // element ================================================================= -const uint32_t MemoryElement::buffer_offset = MemoryElement::validOffset(); +const uint32_t MemoryElement::data_buffer_offset = MemoryElement::validOffset(); uint32_t MemoryElement::validOffset() { @@ -98,10 +111,10 @@ uint32_t MemoryElement::rawSize(uint32_t data_type_size) MemoryElement::MemoryElement(ElementControlBlock* access_bind) : data_ptr((ElementControlBlock*)access_bind) {} -uint32_t MemoryElement::typeSize() const +uint16_t MemoryElement::typeSize() const { auto page_ptr = data_ptr->page_refer; - return ((PageControlBlock*)page_ptr)->byte_count_per_element - buffer_offset; + return page_ptr->sliceRawSize(); } void MemoryElement::accessUpdate(uint64_t time_usec) @@ -109,25 +122,32 @@ void MemoryElement::accessUpdate(uint64_t time_usec) data_ptr->page_refer->accessRecord(time_usec); } -uint8_t MemoryElement::isActived() const +bool MemoryElement::isActived(ElementControlBlock* refer) { - data_ptr->page_refer->lock(); - auto mark = data_ptr->active_mark; - data_ptr->page_refer->release(); + refer->page_refer->lock(); + auto mark = refer->refer_count; + refer->page_refer->release(); return mark; } -void MemoryElement::setActive(uint8_t ste) +void MemoryElement::referAdd() { data_ptr->page_refer->lock(); - data_ptr->active_mark = ste; + data_ptr->refer_count++; + data_ptr->page_refer->release(); +} + +void MemoryElement::referSub() +{ + data_ptr->page_refer->lock(); + data_ptr->refer_count--; data_ptr->page_refer->release(); } unsigned char* MemoryElement::dataLock() { data_ptr->page_refer->lock(); - return ((unsigned char*)data_ptr) + buffer_offset; + return ((unsigned char*)data_ptr) + data_buffer_offset; } void MemoryElement::release() diff --git a/ECSMemoryPool/memory_pages.h b/ECSMemoryPool/memory_pages.h index b6fa67f..17313fa 100644 --- a/ECSMemoryPool/memory_pages.h +++ b/ECSMemoryPool/memory_pages.h @@ -7,8 +7,8 @@ class MemoryPage; /// 内存页访问控制块 /// struct PageControlBlock { - uint16_t active_entities_count = 0; // 活跃element数量,决定是否需要卸载 - uint16_t byte_count_per_element = 32; // 单个element大小,16的倍数 + uint16_t active_elements_count = 0; // 活跃element数量,决定是否需要卸载 + uint16_t byte_count_per_element = 32; // 单个element大小,16的倍数,带ElementControlBlock uint32_t total_buffer_size = 0; // 可用数据缓冲区大小 uint64_t typecode_of_element = 0; // 元素类型标识码 @@ -25,9 +25,9 @@ struct PageControlBlock { /// 元素访问控制块 /// struct ElementControlBlock { - uint8_t active_mark = 0; // 活跃标志 - uint8_t backup_1 = 0; + uint32_t refer_count = 0; // 外部元素的引用数量,活跃标志 uint16_t element_index = 0; // 本元素在Page中的索引 + uint16_t backup_1 = 0; MemoryPage* page_refer = nullptr; // 页面关联指针 void* extend_bind = nullptr; // 绑定控制块内存指针 @@ -50,6 +50,19 @@ public: /// 原始element尺寸 explicit MemoryPage(uint16_t raw_esize_16B, uint64_t typecode); + /// + /// 内存存储的数据元素的尺寸 + /// + /// + uint16_t dataSliceSize() const; + + /// + /// 获取当前活跃元素数量 + /// + /// 变化值 + /// 当前元素数量 + uint16_t getActiveCount(uint16_t inc = 0) const; + /// /// 记录单次访问时间 /// @@ -81,7 +94,7 @@ public: /// 元素索引 /// 是否设置 /// 数据指针 - ElementControlBlock* getElementPtr(int index); + ElementControlBlock* getSlicePtr(int index); /// /// 元素类型码 /// @@ -91,12 +104,12 @@ public: /// 获取单个元素尺寸 /// /// 字节数量 - uint16_t elementSize() const; + uint16_t sliceRawSize() const; /// /// 获取元素数量 /// /// - uint16_t elementCount() const; + uint16_t maxSliceCount() const; }; /// @@ -105,9 +118,9 @@ public: class MemoryElement { private: ElementControlBlock* const data_ptr; - static const uint32_t buffer_offset; public: + static const uint32_t data_buffer_offset; static uint32_t validOffset(); static uint32_t rawSize(uint32_t data_type_size); @@ -121,7 +134,7 @@ public: /// 提取关联元素尺寸 /// /// - uint32_t typeSize() const; + uint16_t typeSize() const; /// /// 更新最终访问时间 @@ -133,12 +146,17 @@ public: /// 数据活跃状态 /// /// - uint8_t isActived() const; + static bool isActived(ElementControlBlock *refer); /// /// 设置数据活跃状态 /// /// - void setActive(uint8_t ste); + void referAdd(); + /// + /// 设置数据活跃状态 + /// + /// + void referSub(); /// /// 锁定数据,返回数据存储内存指针