117 lines
3.0 KiB
C++
117 lines
3.0 KiB
C++
#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(); }
|
||
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_code,page_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(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<uint16_t, void*>(type_size, 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();
|
||
// 跳转到元素重用
|
||
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<T>(refer_ptr);
|
||
}
|
||
};
|