WsComponentPool/ECSMemoryPool/ecs_memorypool.h

132 lines
3.4 KiB
C
Raw Normal View History

2025-09-11 10:36:49 +00:00
#pragma once
#include "ecsmemorypool_global.h"
#include <QJsonObject>
#include <QList>
#include <QHash>
2025-09-27 15:04:35 +00:00
#include <map>
2025-09-11 10:36:49 +00:00
#include <memory_pages.h>
template<typename T>
2025-09-11 14:01:42 +00:00
concept CompenentType = requires(T t, T other, const QJsonObject & in, QJsonObject & out) {
{ T::typeCode() } -> std::same_as<uint64_t>;
{ T::typeSize() } -> std::same_as<uint16_t>;
2025-09-11 10:36:49 +00:00
{ t.loadFrom(in) } -> std::same_as<void>;
{ t.saveTo(out) } -> std::same_as<void>;
};
2025-09-11 14:01:42 +00:00
/// <summary>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>
/// </summary>
/// <typeparam name="T"></typeparam>
2025-09-27 14:22:43 +00:00
template<typename T> class ChunkRefer : protected MemoryChunk {
2025-09-11 14:01:42 +00:00
public:
2025-09-27 15:41:15 +00:00
ChunkRefer(ChunkControlBlock* data) : MemoryChunk(data) { referAdd(); }
2025-09-27 14:22:43 +00:00
ChunkRefer(const ChunkRefer<T> &other) :MemoryChunk(other.data_ptr) { referAdd(); }
virtual ~ChunkRefer() { referSub(); }
2025-09-11 14:01:42 +00:00
T* dataLock() {
2025-09-26 16:46:46 +00:00
return (T*)(MemoryChunk::dataLock());
2025-09-11 14:01:42 +00:00
}
void unlock() {
2025-09-26 16:46:46 +00:00
MemoryChunk::release();
2025-09-11 14:01:42 +00:00
}
2025-09-11 22:36:56 +00:00
2025-09-11 14:01:42 +00:00
};
2025-09-11 10:36:49 +00:00
2025-09-11 14:01:42 +00:00
2025-09-27 15:04:35 +00:00
2025-09-11 14:01:42 +00:00
class ECSMEMORYPOOL_EXPORT ECSMemoryPool {
2025-09-11 10:36:49 +00:00
private:
2025-09-11 14:01:42 +00:00
std::mutex _pool_protected_;
/// <summary>
/// Я<><D0AF>Ĭ<EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ʵ<EFBFBD><CAB5>
/// </summary>
QHash<uint64_t, std::pair<uint16_t, void*>> _basic_component_memory_example;
/// <summary>
/// map<type_code<64><65>page_ptr> <20>ڴ<EFBFBD>ҳ<EFBFBD>
/// </summary>
QMultiHash<uint64_t, MemoryPage*> _storage_pages;
2025-09-11 10:36:49 +00:00
public:
ECSMemoryPool();
2025-09-11 14:01:42 +00:00
/// <summary>
/// ע<><D7A2>Я<EFBFBD><D0AF>Ĭ<EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="one"></param>
2025-09-27 15:04:35 +00:00
template<CompenentType T> void registerComponent(const T& one) {
2025-09-11 14:01:42 +00:00
std::lock_guard<std::mutex> lockx(_pool_protected_);
auto ptr = new char[T::typeSize()];
memcpy(ptr, &one, T::typeSize());
// ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
auto type_code = T::typeCode();
auto type_size = T::typeSize();
2025-09-11 22:36:56 +00:00
_basic_component_memory_example[type_code] = std::make_pair(type_size, (void*)ptr);
2025-09-11 14:01:42 +00:00
}
/// <summary>
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD><C2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
2025-09-27 14:22:43 +00:00
template<CompenentType T> ChunkRefer<T> generate() {
2025-09-11 14:01:42 +00:00
std::lock_guard<std::mutex> lockx(_pool_protected_);
auto type_code = T::typeCode();
2025-09-27 15:41:15 +00:00
ChunkControlBlock* refer_ptr = nullptr;
2025-09-11 14:01:42 +00:00
// <20><>ȡָ<C8A1><D6B8><EFBFBD><EFBFBD><EFBFBD>͹<EFBFBD><CDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ
QList<MemoryPage*> page_list = _storage_pages.values(type_code);
// <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD>
for (auto page_ptr : page_list) {
2025-09-27 15:41:15 +00:00
auto max_chunk_cnt = page_ptr->maxCapacity();
2025-09-11 14:01:42 +00:00
auto active_cnt = page_ptr->getActiveCount();
// <20><><EFBFBD><EFBFBD>У<EFBFBD>˿<EFBFBD><CBBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2025-09-27 15:41:15 +00:00
if (active_cnt < max_chunk_cnt) {
2025-09-11 14:01:42 +00:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>
2025-09-27 15:41:15 +00:00
for (auto eidx = 0; eidx < max_chunk_cnt; eidx++) {
2025-09-26 16:45:04 +00:00
auto slice_ptr = page_ptr->getChunkPtr(eidx);
2025-09-11 14:01:42 +00:00
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
slice_ptr->page_refer->lock();
// <20>þ<EFBFBD>Ԫ<EFBFBD>ؿ<EFBFBD><D8BF><EFBFBD><EFBFBD><EFBFBD>
if (!slice_ptr->refer_count) {
2025-09-11 22:36:56 +00:00
// Ԫ<>ؿ<EFBFBD><D8BF>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>
2025-09-11 14:01:42 +00:00
slice_ptr->refer_count++;
refer_ptr = slice_ptr;
slice_ptr->page_refer->release();
2025-09-11 22:36:56 +00:00
refer_ptr->page_refer->getActiveCount(1);
2025-09-11 14:01:42 +00:00
// <20><>ת<EFBFBD><D7AA>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
goto exists_reuse;
}
else {
slice_ptr->page_refer->release();
}
}
}
}
2025-09-11 22:36:56 +00:00
{
// <20><><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD><C2B5>ڴ<EFBFBD>ҳ
2025-09-26 16:46:46 +00:00
auto new_page = new MemoryPage(MemoryChunk::rawSize(T::typeSize()), type_code);
2025-09-11 22:36:56 +00:00
_storage_pages.insert(type_code, new_page);
2025-09-26 16:45:04 +00:00
refer_ptr = new_page->getChunkPtr(0);
2025-09-11 22:36:56 +00:00
refer_ptr->page_refer->getActiveCount(1);
refer_ptr->refer_count++;
}
2025-09-11 10:36:49 +00:00
2025-09-11 14:01:42 +00:00
exists_reuse:
2025-09-27 14:22:43 +00:00
ChunkRefer<T> temp_inst(refer_ptr);
2025-09-11 22:36:56 +00:00
auto data_pointer = temp_inst.dataLock();
refer_ptr->refer_count--;
auto dpair = _basic_component_memory_example[T::typeCode()];
memcpy(data_pointer, dpair.second, dpair.first);
temp_inst.unlock();
return temp_inst;
2025-09-11 14:01:42 +00:00
}
2025-09-11 10:36:49 +00:00
};