WsComponentPool/ECSMemoryPool/ecs_memorypool.h

129 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "ecsmemorypool_global.h"
#include <QJsonObject>
#include <QList>
#include <QHash>
#include <memory_pages.h>
template<typename T>
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>;
{ t.loadFrom(in) } -> std::same_as<void>;
{ t.saveTo(out) } -> std::same_as<void>;
};
/// <summary>
/// 组件引用符号
/// </summary>
/// <typeparam name="T"></typeparam>
template<typename T> class ComponentRefer : protected MemoryElement {
public:
ComponentRefer(ElementControlBlock* data) : MemoryElement(data) { referAdd(); }
ComponentRefer(const ComponentRefer<T> &other) :MemoryElement(other.data_ptr) { referAdd(); }
virtual ~ComponentRefer() { referSub(); }
T* dataLock() {
return (T*)(MemoryElement::dataLock());
}
void unlock() {
MemoryElement::release();
}
};
class ECSMEMORYPOOL_EXPORT ECSMemoryPool {
private:
std::mutex _pool_protected_;
/// <summary>
/// 携带默认参数数据元素组件内存实例
/// </summary>
QHash<uint64_t, std::pair<uint16_t, void*>> _basic_component_memory_example;
/// <summary>
/// map<type_codepage_ptr> 内存页存储
/// </summary>
QMultiHash<uint64_t, MemoryPage*> _storage_pages;
public:
ECSMemoryPool();
/// <summary>
/// 注册携带默认参数的数据组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="one"></param>
template<CompenentType T> void registerComponent(const T &one) {
std::lock_guard<std::mutex> 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, (void*)ptr);
}
/// <summary>
/// 创建一个新的数据组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
template<CompenentType T> ComponentRefer<T> generate() {
std::lock_guard<std::mutex> lockx(_pool_protected_);
auto type_code = T::typeCode();
ElementControlBlock* refer_ptr = nullptr;
// 获取指定类型关联的内存页
QList<MemoryPage*> 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();
refer_ptr->page_refer->getActiveCount(1);
// 跳转到元素重用
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);
refer_ptr->page_refer->getActiveCount(1);
refer_ptr->refer_count++;
}
exists_reuse:
ComponentRefer<T> temp_inst(refer_ptr);
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;
}
};