commit e83cf9b7cebd767951906318baaf3dfd865d6bf8 Author: codeboss <2422523675@qq.com> Date: Thu Sep 11 18:36:49 2025 +0800 update diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c77d85e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +x64/ +.vs/ \ No newline at end of file diff --git a/ECSMemoryPool.sln b/ECSMemoryPool.sln new file mode 100644 index 0000000..b3fa658 --- /dev/null +++ b/ECSMemoryPool.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECSMemoryPool", "ECSMemoryPool\ECSMemoryPool.vcxproj", "{666EC5D6-70A6-40DA-B92A-364116921A07}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {666EC5D6-70A6-40DA-B92A-364116921A07}.Debug|x64.ActiveCfg = Debug|x64 + {666EC5D6-70A6-40DA-B92A-364116921A07}.Debug|x64.Build.0 = Debug|x64 + {666EC5D6-70A6-40DA-B92A-364116921A07}.Release|x64.ActiveCfg = Release|x64 + {666EC5D6-70A6-40DA-B92A-364116921A07}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A821C833-A8F8-4557-AAEC-84F9281C171F} + EndGlobalSection +EndGlobal diff --git a/ECSMemoryPool/ECSMemoryPool.vcxproj b/ECSMemoryPool/ECSMemoryPool.vcxproj new file mode 100644 index 0000000..4c64a7c --- /dev/null +++ b/ECSMemoryPool/ECSMemoryPool.vcxproj @@ -0,0 +1,114 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {666EC5D6-70A6-40DA-B92A-364116921A07} + QtVS_v304 + 10.0 + 10.0 + $(MSBuildProjectDirectory)\QtMsBuild + + + + DynamicLibrary + v143 + true + Unicode + + + DynamicLibrary + v143 + false + true + Unicode + + + + + + + 5.12.11_msvc2017_64 + core + debug + + + 5.12.11_msvc2017_64 + core + release + + + + + + + + + + + + + + + + + + + + + + stdcpp20 + + + + + true + ECSMEMORYPOOL_LIB;%(PreprocessorDefinitions) + Level3 + true + true + + + Windows + true + + + + + true + ECSMEMORYPOOL_LIB;%(PreprocessorDefinitions) + Level3 + true + true + true + true + + + Windows + false + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ECSMemoryPool/ECSMemoryPool.vcxproj.filters b/ECSMemoryPool/ECSMemoryPool.vcxproj.filters new file mode 100644 index 0000000..f97f06b --- /dev/null +++ b/ECSMemoryPool/ECSMemoryPool.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + qml;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + qrc;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {99349809-55BA-4b9d-BF79-8FDBB0286EB3} + ui + + + {639EADAA-A684-42e4-A9AD-28FC9BCB8F7C} + ts + + + + + Header Files + + + Source Files + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/ECSMemoryPool/ECSMemoryPool.vcxproj.user b/ECSMemoryPool/ECSMemoryPool.vcxproj.user new file mode 100644 index 0000000..41a709a --- /dev/null +++ b/ECSMemoryPool/ECSMemoryPool.vcxproj.user @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ECSMemoryPool/ecs_memorypool.cpp b/ECSMemoryPool/ecs_memorypool.cpp new file mode 100644 index 0000000..be14c36 --- /dev/null +++ b/ECSMemoryPool/ecs_memorypool.cpp @@ -0,0 +1,5 @@ +#include "ecs_memorypool.h" + +ECSMemoryPool::ECSMemoryPool() +{ +} diff --git a/ECSMemoryPool/ecs_memorypool.h b/ECSMemoryPool/ecs_memorypool.h new file mode 100644 index 0000000..d32181c --- /dev/null +++ b/ECSMemoryPool/ecs_memorypool.h @@ -0,0 +1,28 @@ +#pragma once + +#include "ecsmemorypool_global.h" +#include +#include +#include +#include + +template +concept CompenentType = requires(T t, 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; +}; + + +class ECSMEMORYPOOL_EXPORT ECSMemoryPool{ +private: + QList> _storage_pages; + +public: + ECSMemoryPool(); + + template void registerComponent() { + + } +}; diff --git a/ECSMemoryPool/ecsmemorypool_global.h b/ECSMemoryPool/ecsmemorypool_global.h new file mode 100644 index 0000000..5615e5a --- /dev/null +++ b/ECSMemoryPool/ecsmemorypool_global.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#ifndef BUILD_STATIC +# if defined(ECSMEMORYPOOL_LIB) +# define ECSMEMORYPOOL_EXPORT Q_DECL_EXPORT +# else +# define ECSMEMORYPOOL_EXPORT Q_DECL_IMPORT +# endif +#else +# define ECSMEMORYPOOL_EXPORT +#endif diff --git a/ECSMemoryPool/memory_pages.cpp b/ECSMemoryPool/memory_pages.cpp new file mode 100644 index 0000000..dcff6d5 --- /dev/null +++ b/ECSMemoryPool/memory_pages.cpp @@ -0,0 +1,130 @@ +#include "memory_pages.h" + +MemoryPage::MemoryPage(uint16_t element_size, uint64_t typecode) +{ + pcb.byte_count_per_element = element_size; + pcb.total_buffer_size = sizeof(data_buffer); + pcb.typecode_of_element = typecode; +} + +void MemoryPage::accessRecord(uint64_t timepoint_usec) { + std::lock_guard g(pcb.access_protected); + pcb.curr_access_usec = timepoint_usec; + pcb.acc_count_per_cycle++; +} + +uint32_t MemoryPage::timesClear() { + std::lock_guard g(pcb.access_protected); + auto value = pcb.acc_count_per_cycle; + pcb.acc_count_per_cycle = 0; + return value; +} + +std::pair MemoryPage::getRecords() const { + auto data_ptr = const_cast(this); + std::lock_guard g(data_ptr->pcb.access_protected); + return std::make_pair(pcb.curr_access_usec, pcb.acc_count_per_cycle); +} + +char* MemoryPage::getElementPtr(int index) { + auto member_cnt = elementCount(); + auto element_size = elementSize(); + + char* element_ptr = nullptr; + if (index >= 0 && index < member_cnt) { + element_ptr = data_buffer + index * element_size; + } + else if (index < 0 && index >= -member_cnt) { + element_ptr = data_buffer + (member_cnt + index) * element_size; + } + + lock(); + if (element_ptr) { + auto data_ptr = (ElementControlBlock*)element_ptr; + data_ptr->page_refer = this; + data_ptr->element_index = index; + } + release(); + return element_ptr; +} + +void MemoryPage::lock() +{ + pcb.access_protected.lock(); +} + +void MemoryPage::release() { +#pragma warning(push) +#pragma warning(disable : 26110) + pcb.access_protected.unlock(); +#pragma warning(pop) +} + +uint64_t MemoryPage::elementTypeCode() const +{ + auto data_ptr = const_cast(this); + std::lock_guard g(data_ptr->pcb.access_protected); + return pcb.typecode_of_element; +} + +uint16_t MemoryPage::elementSize() 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 cnt = sizeof(data_buffer); + return cnt / this->elementSize(); +} + +uint32_t MemoryElement::validOffset() +{ + uint32_t remains = sizeof(ElementControlBlock) % 8; + uint32_t times = sizeof(ElementControlBlock) / 8; + return (remains ? times + 1 : times) * 8; +} + +uint32_t MemoryElement::rawSize(uint32_t data_type_size) +{ + uint32_t minimal_size = validOffset() + data_type_size; + auto remains = minimal_size % 16; + auto times = minimal_size / 16; + return (remains ? times + 1 : times) * 16; +} + +MemoryElement::MemoryElement(char* access_bind) + : data_ptr((ElementControlBlock*)access_bind) { + buffer_offset = validOffset(); +} + +void MemoryElement::accessRecUpdate(uint64_t time_usec) +{ + data_ptr->page_refer->accessRecord(time_usec); +} + +uint8_t MemoryElement::isActived() const +{ + data_ptr->page_refer->lock(); + auto mark = data_ptr->active_mark; + data_ptr->page_refer->release(); + return mark; +} + +void MemoryElement::setActive(uint8_t ste) +{ + data_ptr->page_refer->lock(); + data_ptr->active_mark = ste; + data_ptr->page_refer->release(); +} + +char* MemoryElement::dataLock() +{ + data_ptr->page_refer->lock(); + return ((char*)data_ptr) + buffer_offset; +} + +void MemoryElement::release() +{ + data_ptr->page_refer->release(); +} diff --git a/ECSMemoryPool/memory_pages.h b/ECSMemoryPool/memory_pages.h new file mode 100644 index 0000000..5868268 --- /dev/null +++ b/ECSMemoryPool/memory_pages.h @@ -0,0 +1,145 @@ +#pragma once +#include + +class MemoryPage; + +/// +/// ÄÚ´æÒ³·ÃÎÊ¿ØÖÆ¿é +/// +struct PageControlBlock { + uint16_t active_entities_count = 0; // »îÔ¾elementÊýÁ¿£¬¾ö¶¨ÊÇ·ñÐèÒªÐ¶ÔØ + + uint16_t byte_count_per_element = 32; // µ¥¸öelement´óС£¬16µÄ±¶Êý + uint32_t total_buffer_size = 0; // ¿ÉÓÃÊý¾Ý»º³åÇø´óС + uint64_t typecode_of_element = 0; // ÔªËØÀàÐͱêʶÂë + + uint64_t curr_access_usec = 0; // ×î½ü·ÃÎÊʱ¼äµã£¬lsb£ºus + uint32_t acc_count_per_cycle = 0; // µ¥ÖÜÆÚÄÚÀÛ»ý·ÃÎÊ´ÎÊý + uint32_t un_used = 0; + + std::mutex access_protected; // ÄÚ´æÊý¾Ý·ÃÎʱ£»¤Ëø +}; +/// +/// ÄÚ´æÒ³Ãæ16K´óС +/// +class MemoryPage { +private: + PageControlBlock pcb; + char data_buffer[16 * 1024 - (sizeof(PageControlBlock) / 8 + 1) * 8] = {}; + +public: + /// + /// ¹¹½¨ÄÚ´æÒ³ + /// + /// ԭʼelement³ß´ç + explicit MemoryPage(uint16_t raw_element_size_16B, uint64_t typecode); + + /// + /// ¼Ç¼µ¥´Î·ÃÎÊʱ¼ä + /// + /// + void accessRecord(uint64_t timepoint_usec); + /// + /// Çå³ý·ÃÎÊ´ÎÊý¼Ç¼ + /// + /// ÉÏÒ»ÖÜÆÚÀÛ»ý´ÎÊý + uint32_t timesClear(); + /// + /// »ñÈ¡·ÃÎʼǼ + /// + /// {×î½ü·ÃÎÊʱ¼ä,ÀÛ»ý´ÎÊý} + std::pair getRecords() const; + + /// + /// ¼ÓËø£¬ÔÚrelease֮ǰ²»ÄÜ·ÃÎʱ¾ÀàÐÍÈκνӿڣ¬·ñÔò»áÔì³ÉËÀËø + /// + void lock(); + /// + /// ½âËø + /// + void release(); + + /// + /// »ñÈ¡elementÔªËØÊý¾Ý·ÃÎÊÖ¸Õë + /// + /// ÔªËØË÷Òý + /// ÊÇ·ñÉèÖà + /// Êý¾ÝÖ¸Õë + char* getElementPtr(int index); + /// + /// ÔªËØÀàÐÍÂë + /// + /// + uint64_t elementTypeCode() const; + /// + /// »ñÈ¡µ¥¸öÔªËØ³ß´ç + /// + /// ×Ö½ÚÊýÁ¿ + uint16_t elementSize() const; + /// + /// »ñÈ¡ÔªËØÊýÁ¿ + /// + /// + uint16_t elementCount() const; +}; + + +/// +/// ÔªËØ·ÃÎÊ¿ØÖÆ¿é +/// +struct ElementControlBlock { + uint8_t active_mark = 0; // »îÔ¾±êÖ¾ + uint8_t backup_1 = 0; + uint16_t byte_count = 16; // ¸ÃÔªËØ×Ö½Ú³¤¶È£¬16µÄ±¶Êý + uint16_t element_index = 0; // ±¾ÔªËØÔÚPageÖеÄË÷Òý + uint16_t backup_2 = 0; + MemoryPage* page_refer = nullptr; // Ò³Ãæ¹ØÁªÖ¸Õë + void* extend_bind = nullptr; // °ó¶¨¿ØÖÆ¿éÄÚ´æÖ¸Õë +}; + + +/// +/// ÄÚ´æÔªËØ·ÃÎÊ½Ó¿Ú +/// +class MemoryElement { +private: + ElementControlBlock* const data_ptr; + uint32_t buffer_offset = 0; + +public: + static uint32_t validOffset(); + static uint32_t rawSize(uint32_t data_type_size); + + /// + /// ¹¹½¨ÄÚ´æÔªËØ·ÃÎÊ½Ó¿Ú + /// + /// + MemoryElement(char* access_bind); + + /// + /// ¸üÐÂ×îÖÕ·ÃÎÊʱ¼ä + /// + /// + void accessRecUpdate(uint64_t time_usec); + + /// + /// Êý¾Ý»îԾ״̬ + /// + /// + uint8_t isActived() const; + /// + /// ÉèÖÃÊý¾Ý»îԾ״̬ + /// + /// + void setActive(uint8_t ste); + + /// + /// Ëø¶¨Êý¾Ý£¬·µ»ØÊý¾Ý´æ´¢ÄÚ´æÖ¸Õë + /// + /// + char* dataLock(); + /// + /// ½âËøÊý¾Ý + /// + void release(); +}; \ No newline at end of file