name 字符串优化

This commit is contained in:
ouczbs 2024-11-20 17:26:54 +08:00
parent a6458a82c0
commit f51befaff0
28 changed files with 447 additions and 225 deletions

View File

@ -1,4 +1,6 @@
{
"metadatas": [],
"includes": []
}
metadatas:
- guid: 7dfa8412-3278-43f6-b332-ac09a132025f
name: ""
t_hash: "api::ShaderProgram\x06 mOwner!<21>/engine/assets/shader/simple.frag"
meta: ~
includes: ~

View File

@ -0,0 +1,6 @@
metadatas:
- guid: 47c28b8c-f2aa-4357-a12d-7212de6e3a9e
name: ""
t_hash: "api::ShaderProgram\x06 mOwner!<21>/engine/assets/shader/simple.frag"
meta: ~
includes: ~

View File

@ -24,7 +24,7 @@ namespace api {
for (auto& elem : bundle.GetAll())
std::visit([&](auto& handle) {
using T = std::decay_t<decltype(*handle)>;
SerializedMeta meta{ handle.guid, handle->Name(), meta_name<T>().view() };
SerializedMeta meta{ handle.guid, handle->Name(), meta_name<T>() };
if constexpr (is_meta_v<T>) {
meta.meta = handle->Meta();
}

View File

@ -31,7 +31,7 @@ namespace api
template<typename T>
const SerializedMeta* FetchMeta() const;
template<typename T>
const SerializedMeta* FetchMeta(string_view asset_name) const;
const SerializedMeta* FetchMeta(Name asset_name) const;
void Add(const SerializedMeta& meta) {
metadatas.push_back(meta);
};

View File

@ -4,7 +4,7 @@ namespace api
template<typename T>
inline const SerializedMeta* MetaBundle::FetchMeta() const
{
string_view name = meta_name<typename T::BaseResource>().view();
Name name = meta_name<typename T::BaseResource>();
for (auto& elem : metadatas)
{
if (elem.t_hash == name)
@ -13,9 +13,9 @@ namespace api
return nullptr;
}
template<typename T>
inline const SerializedMeta* MetaBundle::FetchMeta(string_view asset_name) const
inline const SerializedMeta* MetaBundle::FetchMeta(Name asset_name) const
{
string_view name = meta_name<typename T::BaseResource>().view();
Name name = meta_name<typename T::BaseResource>();
for (auto& elem : metadatas)
{
if (elem.t_hash == name && asset_name == elem.name)

View File

@ -45,19 +45,20 @@ namespace api {
{
DestroyGraph();
}
void ModuleManagerImpl::CreateModule(Name name, bool shared)
void ModuleManagerImpl::CreateModule(Name name, bool is_shared)
{
bool hotfix = true;
IModule* module = shared ?
IModule* module = is_shared ?
spawnDynamicModule(name, hotfix) :
spawnStaticModule(name);
if (!module) { return; }
mModuleBlocks[name] = ModuleBlock{false, false};
ModuleBlock& block = mModuleBlocks[name];
auto& moduleInfo = module->mInfo;
Name shared("shared");
for (auto& dep : moduleInfo.dependencies) {
if(auto it = mModuleBlocks.find(dep.name); it == mModuleBlocks.end())
CreateModule(dep.name, dep.kind == pmr::FName("shared"));
CreateModule(dep.name, dep.kind == shared);
}
module->OnLoad(mInfo.argc, mInfo.argv);
block.isLoad = true;

View File

@ -19,7 +19,7 @@ namespace gen {
else if constexpr (std::is_floating_point_v<T>) {
*(T*)(ptr) = (T)yyjson_get_real(val);
}
else if constexpr (is_string_v<T>) {
else if constexpr (is_string_view_v<T> || is_string_v<T>) {
*(T*)(ptr) = yyjson_get_str(val);
}
else {
@ -40,14 +40,12 @@ namespace gen {
else if constexpr (std::is_floating_point_v<T>) {
return yyjson_mut_real(doc, *(T*)(ptr));
}
else if constexpr (is_string_view_v<T>) {
return yyjson_mut_str(doc, std::string_view(*(T*)ptr).data());
}
else if constexpr (is_string_v<T>) {
if constexpr (requires(T * t) { t->data(); }) {
return yyjson_mut_str(doc, ((T*)ptr)->data());
}
else {
return yyjson_mut_str(doc, std::string(*(T*)ptr).data());
}
}
else {
//static_assert(false, "unknown json write type");
}

View File

@ -33,11 +33,11 @@ namespace api {
#include "../register.inl"
#undef RegisterAny
}
inline consteval size_t VJsonSerdeRead() {
return string_hash("JsonSerdeRead");
inline Name VJsonSerdeRead() {
return Name("JsonSerdeRead");
}
inline consteval size_t VJsonSerdeWrite() {
return string_hash("JsonSerdeWrite");
inline Name VJsonSerdeWrite() {
return Name("JsonSerdeWrite");
}
template<typename T>
inline void JsonArchive::Register()

View File

@ -6,14 +6,20 @@ namespace gen {
struct Meta {};
template<typename T>
concept is_string_v = requires(T t) {
{ static_cast<std::string>(t) } -> std::convertible_to<std::string>;
{ static_cast<std::string>(t) } -> std::same_as<std::string>;
};
template<typename T>
concept is_serde_v = std::is_same_v<T, bool> || std::is_integral_v<T> || std::is_floating_point_v<T> || is_string_v<T> || std::is_enum_v<T>;
concept is_string_view_v = requires(T t) {
{ static_cast<std::string_view>(t) } -> std::same_as<std::string_view>;
};
template<typename T>
concept is_serde_v = std::is_same_v<T, bool> || std::is_integral_v<T> || std::is_floating_point_v<T> || is_string_v<T> || std::is_enum_v<T>
|| is_string_view_v<T>;
}
namespace api {
using meta::result;
using std::string_view;
using pmr::Name;
enum class SerializeError : char
{
SERDE_EMPTY,

View File

@ -16,6 +16,9 @@ namespace gen {
else if constexpr (std::is_enum_v<T>) {
*(T*)(ptr) = (T)node.as<uint32_t>();
}
else if constexpr (is_string_view_v<T>) {
*(T*)(ptr) = node.as<std::string_view>();
}
else if constexpr (is_string_v<T>) {
*(T*)(ptr) = node.as<std::string>();
}
@ -31,14 +34,12 @@ namespace gen {
else if constexpr (std::is_enum_v<T>) {
return YAML::Node{ *(uint32_t*)(T*)ptr };
}
else if constexpr (is_string_view_v<T>) {
return YAML::Node{ std::string_view(*(T*)ptr).data() };
}
else if constexpr (is_string_v<T>) {
if constexpr (requires(T * t) { t->data(); }) {
return YAML::Node{ ((T*)ptr)->data()};
}
else {
return YAML::Node{ std::string(*(T*)ptr).data() };
}
}
else {
//static_assert(false, "unknown json write type");
}

View File

@ -7,11 +7,11 @@ namespace api {
#include "../register.inl"
#undef RegisterAny
}
inline consteval size_t VYamlSerdeRead() {
return string_hash("YamlSerdeRead");
inline Name VYamlSerdeRead() {
return Name("YamlSerdeRead");
}
inline consteval size_t VYamlSerdeWrite() {
return string_hash("YamlSerdeWrite");
inline Name VYamlSerdeWrite() {
return Name("YamlSerdeWrite");
}
template<typename T>
inline void YamlArchive::Register()

View File

@ -27,8 +27,8 @@ namespace api {
void Execute(FRenderView& view);
void Clear();
TextureDesc Resource(Name name) {
constexpr size_t surface = string_hash("surface");
if (name.Hash() == surface) {
static Name surface("surface");
if (name == surface) {
return mSurface;
}
auto it = mResourceTable.find(name);

View File

@ -29,15 +29,15 @@ namespace api
}
shaderc_shader_kind GlslToSpirv::GetShaderKind(Name name)
{
switch (name.Hash())
{
case string_hash(".vert"): return shaderc_shader_kind::shaderc_vertex_shader;
case string_hash(".geom"): return shaderc_shader_kind::shaderc_geometry_shader;
case string_hash(".tese"): return shaderc_shader_kind::shaderc_tess_evaluation_shader;
case string_hash(".tesc"): return shaderc_shader_kind::shaderc_tess_control_shader;
case string_hash(".frag"): return shaderc_shader_kind::shaderc_fragment_shader;
default: return shaderc_shader_kind::shaderc_miss_shader;
static Name vert(".vert");
static Name frag(".frag");
if (name == vert) {
return shaderc_shader_kind::shaderc_vertex_shader;
}
if(name == frag) {
return shaderc_shader_kind::shaderc_fragment_shader;
}
throw std::runtime_error("unsupport type");
}
ShaderStage GlslToSpirv::GetShaderStage(shaderc_shader_kind kind)
{

View File

@ -2,7 +2,6 @@
#include <vector>
#include <memory_resource>
namespace pmr {
using std::pmr::unsynchronized_pool_resource;
using std::pmr::memory_resource;
using std::pmr::vector;
class ZLIB_API FrameAllocator : public memory_resource {

View File

@ -1,81 +1,217 @@
#pragma once
#include <mutex>
#include <array>
#include "singleton.h"
#include "frame_allocator.h"
#include <unordered_map>
namespace pmr
{
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
using table = std::pmr::unordered_map<T1, T2, Hasher>;
using std::pmr::string;
static consteval inline size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
struct Name {
private:
size_t hash;
#ifdef API_DEBUG
std::string_view value;
#endif // API_DEBUG
public:
Name():hash(InvalidValue()) {};
template<size_t N>
Name(const char(&str)[N]) noexcept;
Name(const char* str)noexcept;
Name(const std::string& str)noexcept;
Name(const string& str)noexcept;
Name(std::string_view str)noexcept;
auto operator<=>(const Name& other) const noexcept { return hash <=> other.hash; };
const char* data()const { return ToStringView().data(); }
constexpr size_t Hash() const noexcept { return hash; }
std::string ToString() const;
const std::string_view ToStringView() const;
operator size_t()const {return hash;}
operator std::string() const { return ToString(); }
};
class CName {
private:
size_t hash;
std::string_view value;
public:
constexpr CName() noexcept : hash{ InvalidValue() } {}
constexpr CName(string str) noexcept : hash{ string_hash(str) }, value(str) {}
constexpr CName(std::string_view str) noexcept : hash{ string_hash(str) } ,value(str) {}
template<size_t N>
constexpr CName(const char(&str)[N]) noexcept : hash{ string_hash(str) }, value(str) {}
const char* data()const { return Value().data(); }
constexpr size_t Hash() const noexcept { return hash; }
constexpr std::string_view Value() const noexcept { return value; }
constexpr bool Valid() const noexcept { return hash != InvalidValue(); }
operator Name() {return Name(value);}
explicit constexpr operator bool() const noexcept { return Valid(); }
constexpr auto operator<=>(const CName& rhs) const noexcept { return hash <=> rhs.hash; };
bool operator==(const CName& other) const { return hash == other.hash; }
std::string ToString() const { return std::string(value); };
operator std::string() const { return ToString(); }
};
inline bool operator==(const CName& cname, const Name& name) {
return cname.Hash() == name.Hash();
}
namespace pmr {
template <class T>
constexpr inline void hash_combine(size_t& seed, const T& v) noexcept
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
consteval static CName FName(std::string_view view) { return CName{ view }; };
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
using table = std::pmr::unordered_map<T1, T2, Hasher>;
using std::pmr::string;
class Name {
static constexpr uint32_t IS_USED_MASK = 1u << 29u;
static constexpr uint32_t STRING_ENTRY_HANDLE_BITS = 29u;
static constexpr uint32_t STRING_ENTRY_HANDLE_MASK = (1u << 29u) - 1u;
static constexpr uint32_t MAX_STRING_SIZE = 1023u;
static constexpr uint32_t MAX_SLOT_POOL_ARRAY_SIZE = 256u;
static constexpr uint32_t MAX_MEMORY_BLOCK_ARRAY_SIZE = 8192u;
struct StringEntryHandle
{
static constexpr uint16_t MEMORY_BLOCK_INDEX_MASK = (1u << 13u) - 1u;
private:
uint16_t empty3_memoryBlockIndex13;
uint16_t memoryBlockAlignedOffset16;
public:
StringEntryHandle()
: empty3_memoryBlockIndex13(0u), memoryBlockAlignedOffset16(0u){}
StringEntryHandle(uint32_t stringEntryHandleValue)
: StringEntryHandle(static_cast<uint16_t>(stringEntryHandleValue >> 16)& MEMORY_BLOCK_INDEX_MASK, static_cast<uint16_t>(stringEntryHandleValue)) {}
StringEntryHandle(uint16_t memoryBlockIndex, uint16_t memoryBlockAlignedOffset)
: empty3_memoryBlockIndex13(memoryBlockIndex), memoryBlockAlignedOffset16(memoryBlockAlignedOffset) {}
uint16_t GetMemoryBlockIndex() const {
return empty3_memoryBlockIndex13;
}
uint16_t GetMemoryBlockAlignedOffset() const {
return memoryBlockAlignedOffset16;
}
uint32_t GetStringEntryHandleValue() const {
return static_cast<uint32_t>(empty3_memoryBlockIndex13) << 16 | memoryBlockAlignedOffset16;
}
};
struct StringEntryHeader
{
static constexpr uint16_t SIZE_MASK = (1u << 10u) - 1u;
static constexpr uint16_t STRING_HASH_PROBE_MASK = ((1u << 6u) - 1u) << 10u;
private:
uint16_t stringHashProbe6_size10;
public:
void Init(const uint8_t stringHashProbe, const uint16_t size) {
stringHashProbe6_size10 = (STRING_HASH_PROBE_MASK & (static_cast<uint16_t>(stringHashProbe) << 10u)) | (SIZE_MASK & size);
}
uint16_t GetSize() const { return SIZE_MASK & stringHashProbe6_size10; }
operator uint16_t() { return stringHashProbe6_size10; }
};
struct StringEntry
{
private:
StringEntryHeader stringEntryHeader;
char data[MAX_STRING_SIZE];
public:
StringEntryHeader GetStringEntryHeader() const {
return stringEntryHeader;
}
void SetStringEntryHeader(StringEntryHeader _stringEntryHeader) {
stringEntryHeader = _stringEntryHeader;
}
const char* GetData() const { return data; };
};
struct HashInfo {
static constexpr uint32_t SLOT_POOL_INDEX_MASK = (1u << 8u) - 1u;
static constexpr uint32_t SLOT_HASH_PROBE_MASK = ((1u << 3u) - 1) << 13u;
static constexpr uint32_t STRING_HASH_PROBE_MASK = (1u << 6u) - 1;
const char* data;
StringEntryHeader stringEntryHeader;
uint16_t slotProbe3_empty21_slotPool8;
uint32_t slotIndex32;
HashInfo(std::string_view view) {
uint64_t hash = string_hash(view);
uint32_t Hi = static_cast<uint32_t>(hash >> 32);
uint32_t Lo = static_cast<uint32_t>(hash);
slotIndex32 = Lo;
slotProbe3_empty21_slotPool8 = (SLOT_HASH_PROBE_MASK & (Hi >> 16)) | (SLOT_POOL_INDEX_MASK & Hi);
stringEntryHeader.Init((Hi >> 8u) & STRING_HASH_PROBE_MASK, view.size());
data = view.data();
}
const char* GetData() {
return data;
}
uint32_t GetSlotIndex() const{
return slotIndex32;
}
StringEntryHeader GetStringEntryHeader() const {
return stringEntryHeader;
}
uint32_t GetSlotPoolIndex() const {
return SLOT_POOL_INDEX_MASK & slotProbe3_empty21_slotPool8;
}
template<uint32_t mask>
uint32_t GetSlotHashProbe() const
{
return mask | (SLOT_HASH_PROBE_MASK & slotProbe3_empty21_slotPool8) << 16;
}
};
struct Slot
{
static constexpr uint32_t SLOT_HASH_PROBE_MASK = ((1u << 3u) - 1) << 29u;
static constexpr uint32_t STRING_ENTRY_HANDLE_MASK = (1u << 29u) - 1u;
static constexpr uint32_t MEMORY_BLOCK_ALIGNED_OFFSET_MASK = (1u << 16u) - 1u;
static constexpr uint32_t MEMORY_BLOCK_INDEX_MASK = ((1u << 13u) - 1u);
private:
uint32_t slotHashProbe3_stringEntryHandle29;
public:
bool IsTargetSlot(HashInfo hashInfo) const;
bool IsUsed() const{ return (slotHashProbe3_stringEntryHandle29 & IS_USED_MASK) == IS_USED_MASK; }
uint32_t GetSlotHashProbe() const { return SLOT_HASH_PROBE_MASK & slotHashProbe3_stringEntryHandle29; };
StringEntryHandle GetStringEntryHandle() const {
return StringEntryHandle((slotHashProbe3_stringEntryHandle29 >> 16) & MEMORY_BLOCK_INDEX_MASK, slotHashProbe3_stringEntryHandle29 & MEMORY_BLOCK_ALIGNED_OFFSET_MASK);
}
uint32_t GetStringEntryHandleValue() const { return slotHashProbe3_stringEntryHandle29 & STRING_ENTRY_HANDLE_BITS; };
uint32_t GetSlotValue() const { return slotHashProbe3_stringEntryHandle29; };
void Load(uint32_t slotHashProbeValue,StringEntryHandle stringEntryHandle) {
slotHashProbe3_stringEntryHandle29 = slotHashProbeValue | stringEntryHandle.GetStringEntryHandleValue();
}
void Load(Slot srcSlot) {slotHashProbe3_stringEntryHandle29 = srcSlot.slotHashProbe3_stringEntryHandle29;}
};
struct SlotPool
{
friend class Name;
static constexpr double SLOT_POOL_RESIZE_USAGE_RATE = 0.9;
static constexpr uint32_t SLOT_POOL_INITIALIZE_SIZE = 256u;
private:
uint32_t capcity;
uint32_t size;
Slot* slotArray;
std::mutex mutex;
public:
Slot& FindUnusedOrTargetSlot(HashInfo hashInfo);
Slot& FindUnusedSlot(HashInfo hashInfo);
void AutoResize();
void Resize();
};
struct StringEntryMemoryManager
{
friend class Name;
static constexpr uint32_t ALIGN_BYTES = 2u;
static constexpr uint32_t MAX_MEMORY_BLOCK_SIZE = (1u << 16u) * 2u;
private:
uint16_t currentMemoryBlockIndex;
uint16_t currentMemoryBlockAlignedCursor;
char* memoryBlockArray[MAX_MEMORY_BLOCK_ARRAY_SIZE];
std::mutex mutex;
public:
StringEntryMemoryManager();
StringEntry* GetStringEntry(StringEntryHandle stringEntryHandle) const;
StringEntryHandle AllocateStringEntry(StringEntryHeader stringEntryHeader, const char* data);
private:
void CreateNewMemoryBlock();
};
using tSlotPoolArray = std::array<SlotPool, MAX_SLOT_POOL_ARRAY_SIZE>;
inline UNIQUER_STATIC(tSlotPoolArray, slotPoolArray, "pmr::name::slotPoolArray")
inline UNIQUER_STATIC(StringEntryMemoryManager, stringEntryMemoryManager, "pmr::name::stringEntryMemoryManager")
uint32_t flag3_memory29;
public:
Name()noexcept : flag3_memory29(0) {};
Name(std::string view) noexcept : flag3_memory29(MakeInterned(view)) {};
Name(std::string_view view) noexcept : flag3_memory29(MakeInterned(view)) {};
template<size_t N>
Name(const char(&str)[N]) noexcept : Name(std::string_view(str)) {}
Name(const char* str)noexcept : Name(std::string_view(str)){};
auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; };
uint32_t MakeInterned(std::string_view view);
uint32_t Hash() const{
return flag3_memory29;
}
operator uint32_t() const {
return flag3_memory29;
}
operator std::string_view()const {
return ToStringView();
}
operator std::string()const {
return ToString();
}
const char* data()const {
if (!flag3_memory29)return nullptr;
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
return stringEntry->GetData();
}
std::string_view ToStringView() const
{
if (!flag3_memory29)return "";
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
return std::string_view(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize());
}
std::string ToString() const
{
if (!flag3_memory29)return "";
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29));
return std::string(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize());
}
};
}
namespace std {
template<>
struct hash<::pmr::CName>
{
size_t operator()(const ::pmr::CName& name) const noexcept
{
return name.Hash();
}
};
template<>
struct hash<::pmr::Name>
{
size_t operator()(const ::pmr::Name& name) const noexcept
uint32_t operator()(const ::pmr::Name& name) const noexcept
{
return name.Hash();
}

View File

@ -1,74 +1,151 @@
#include "name.h"
constexpr inline size_t meta_align_size(size_t size, size_t alignment = 8) {
return (size + alignment - 1) / alignment * alignment;
}
XMALLOC_API void* xmalloc(size_t size);
namespace pmr {
using NameTable_t = table<size_t,const string>;
inline NameTable_t& TableRef() {
UNIQUER_STATIC(NameTable_t, Table, "pmr::nametable")
return UNIQUER_VAL(Table);
}
struct NameTable {
static const string& Find(size_t id);
template<typename T>
static std::string_view MakePair(size_t id, T&& str);
};
template<typename T>
inline std::string_view NameTable::MakePair(size_t id, T&& str)
inline bool Name::Slot::IsTargetSlot(HashInfo hashInfo) const
{
auto& Table = TableRef();
auto it = Table.find(id);
if (it == Table.end()) {
auto it2 = Table.emplace(std::make_pair(id, string(str, Table.get_allocator())));
if (it2.second) {
return it2.first->second;
}
return nullptr;
}
return it->second;
}
inline const string& NameTable::Find(size_t id)
if (GetSlotHashProbe() == hashInfo.GetSlotHashProbe<IS_USED_MASK>())
{
auto& Table = TableRef();
auto it = Table.find(id);
if (it == Table.end()) {
static string empty("", Table.get_allocator());
return empty;
}
return it->second;
}
#ifdef API_DEBUG
#define MAKE_NAME_PAIR(hash, str) value = NameTable::MakePair(hash, str)
#define NAME_TO_STRING value
#else
#define MAKE_NAME_PAIR(hash, str) NameTable::MakePair(hash, str)
#define NAME_TO_STRING NameTable::Find(hash)
#endif
inline std::string Name::ToString() const
const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(GetStringEntryHandle());
auto entryHeader = stringEntry->GetStringEntryHeader();
if (entryHeader == hashInfo.GetStringEntryHeader() && 0 == strncmp(stringEntry->GetData(), hashInfo.GetData(), entryHeader.GetSize()))
{
return std::string(NAME_TO_STRING);
return true;
}
inline const std::string_view Name::ToStringView() const
}
return false;
}
inline Name::Slot& Name::SlotPool::FindUnusedOrTargetSlot(HashInfo hashInfo)
{
return std::string_view(NAME_TO_STRING);
}
inline Name::Name(const char* str) noexcept: hash(string_hash(str))
const uint32_t SLOT_POOL_CAPCITY_MASK = capcity - 1;
for (uint32_t slotIndex = hashInfo.GetSlotIndex() & SLOT_POOL_CAPCITY_MASK; true; slotIndex = (slotIndex + 1) & SLOT_POOL_CAPCITY_MASK)
{
MAKE_NAME_PAIR(hash, str);
}
template<std::size_t N>
inline Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str))
Slot& slot = slotArray[slotIndex];
if (!slot.IsUsed() || slot.IsTargetSlot(hashInfo))
{
MAKE_NAME_PAIR(hash, str);
return slot;
}
inline Name::Name(const std::string& str) noexcept : hash(string_hash(str))
}
}
inline Name::Slot& Name::SlotPool::FindUnusedSlot(HashInfo hashInfo)
{
MAKE_NAME_PAIR(hash, str);
}
inline Name::Name(std::string_view str) noexcept : hash(string_hash(str))
const uint32_t SLOT_POOL_CAPCITY_MASK = capcity - 1;
for (uint32_t slotIndex = hashInfo.GetSlotIndex() & SLOT_POOL_CAPCITY_MASK; true; slotIndex = (slotIndex + 1) & SLOT_POOL_CAPCITY_MASK)
{
MAKE_NAME_PAIR(hash, str);
}
inline Name::Name(const string& str)noexcept : hash(string_hash(str))
Slot& slot = slotArray[slotIndex];
if (!slot.IsUsed())
{
MAKE_NAME_PAIR(hash, str);
return slot;
}
}
}
inline void Name::SlotPool::AutoResize()
{
if (size > SLOT_POOL_RESIZE_USAGE_RATE * capcity)
{
Resize();
}
}
inline void Name::SlotPool::Resize()
{
uint32_t oldCapcity = capcity;
Slot* oldSlotArray = slotArray;
capcity = oldCapcity * 2;
slotArray = reinterpret_cast<Slot*>(xmalloc(capcity * sizeof(Slot)));
//std::memset(slotArray, 0, capcity * sizeof(Slot));
auto& stringEntryMemoryManager = UNIQUER_VAL(stringEntryMemoryManager);
for (uint32_t slotIndex = 0; slotIndex < size; slotIndex++)
{
const Name::Slot& oldSlot = oldSlotArray[slotIndex];
StringEntry* stringEntry = stringEntryMemoryManager.GetStringEntry(oldSlotArray[slotIndex].GetStringEntryHandle());
const HashInfo hashInfo(std::string_view(stringEntry->GetData(), stringEntry->GetStringEntryHeader().GetSize()));
Name::Slot& slot = FindUnusedSlot(hashInfo);
slot.Load(oldSlot);
}
std::free(oldSlotArray);
}
inline Name::StringEntryMemoryManager::StringEntryMemoryManager()
{
auto& slotPoolArray = UNIQUER_VAL(slotPoolArray);
for (auto& slotPool : slotPoolArray)
{
slotPool.size = 0;
slotPool.capcity = SlotPool::SLOT_POOL_INITIALIZE_SIZE;
slotPool.slotArray = (Slot*)(xmalloc(SlotPool::SLOT_POOL_INITIALIZE_SIZE * sizeof(Slot)));
std::memset(slotPool.slotArray, 0, SlotPool::SLOT_POOL_INITIALIZE_SIZE);
}
currentMemoryBlockIndex = 0;
currentMemoryBlockAlignedCursor = 0;
memoryBlockArray[0] = (char*)(xmalloc(MAX_MEMORY_BLOCK_SIZE));
std::memset(memoryBlockArray[0], 0, MAX_MEMORY_BLOCK_SIZE);
}
inline Name::StringEntry* Name::StringEntryMemoryManager::GetStringEntry(StringEntryHandle stringEntryHandle) const
{
return reinterpret_cast<Name::StringEntry*>(memoryBlockArray[stringEntryHandle.GetMemoryBlockIndex()] + stringEntryHandle.GetMemoryBlockAlignedOffset() * ALIGN_BYTES);
}
inline Name::StringEntryHandle Name::StringEntryMemoryManager::AllocateStringEntry(StringEntryHeader stringEntryHeader, const char* data)
{
const uint32_t size = meta_align_size(sizeof(StringEntryHeader) + stringEntryHeader.GetSize(), ALIGN_BYTES);
const uint32_t alignedSize = size >> 1;
StringEntryHandle stringEntryHandle{};
{
std::unique_lock<std::mutex> lock(mutex);
if (((static_cast<uint32_t>(currentMemoryBlockAlignedCursor) + alignedSize) << 1) >= MAX_MEMORY_BLOCK_SIZE)
{
CreateNewMemoryBlock();
}
stringEntryHandle = StringEntryHandle(currentMemoryBlockIndex, currentMemoryBlockAlignedCursor);
currentMemoryBlockAlignedCursor += alignedSize;
}
StringEntry* stringEntry = GetStringEntry(stringEntryHandle);
stringEntry->SetStringEntryHeader(stringEntryHeader);
memcpy(const_cast<char*>(stringEntry->GetData()), data, stringEntryHeader.GetSize());
return stringEntryHandle;
}
inline void Name::StringEntryMemoryManager::CreateNewMemoryBlock()
{
if (currentMemoryBlockIndex >= (MAX_MEMORY_BLOCK_ARRAY_SIZE - 1))
throw std::runtime_error("Interned string only supports a maximum of 1GB memory.");
currentMemoryBlockIndex += 1;
currentMemoryBlockAlignedCursor = 0;
memoryBlockArray[currentMemoryBlockIndex] = (char*)(xmalloc(MAX_MEMORY_BLOCK_SIZE));
std::memset(memoryBlockArray[currentMemoryBlockIndex], 0, MAX_MEMORY_BLOCK_SIZE);
}
inline uint32_t Name::MakeInterned(std::string_view view)
{
if (view.empty()) {
return 0u;
}
HashInfo hashInfo(view);
auto& slotPool = UNIQUER_VAL(slotPoolArray)[0];
uint32_t slotValue = 0u;
{
std::unique_lock<std::mutex> lock(slotPool.mutex);
slotPool.AutoResize();
Name::Slot& slot = slotPool.FindUnusedOrTargetSlot(hashInfo);
if (!slot.IsUsed())
{
slotPool.size++;
StringEntryHandle stringEntryHandle = UNIQUER_VAL(stringEntryMemoryManager).AllocateStringEntry(hashInfo.GetStringEntryHeader(), hashInfo.GetData());
slot.Load(hashInfo.GetSlotHashProbe<IS_USED_MASK>(), stringEntryHandle);
}
slotValue = slot.GetSlotValue();
}
return slotValue;
}
#undef MAKE_NAME_PAIR
#undef NAME_TO_STRING
}

View File

@ -39,7 +39,7 @@ namespace refl {
operator bool()const { return cls && ptr; }
bool Check(const UClass* parent) const;
template<typename T>
T FindVtable(size_t name)const;
T FindVtable(Name name)const;
bool Construct(span<Any> ArgsList) const;
Any New(pmr::memory_resource* pool)const;

View File

@ -44,7 +44,7 @@ namespace refl{
return any;
}
template<typename T>
inline T Any::FindVtable(size_t name) const
inline T Any::FindVtable(Name name) const
{
return (T)cls->vtable.Find(name);
}

View File

@ -1,12 +1,7 @@
#pragma once
#include "field.h"
constexpr inline size_t meta_align_size(size_t size, size_t alignment = 8) {
return (size + alignment - 1) / alignment * alignment;
}
namespace gen {
using refl::real_type_t;
using pmr::CName;
using pmr::FName;
template<typename T, size_t hash>
struct MetaImpl {};
template<typename T>
@ -38,16 +33,16 @@ namespace refl {
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
template<typename T, typename Obj>
static FieldPtr MemberField(T Obj::* ptr, CName name, const MemberData& data = {});
static FieldPtr MemberField(T Obj::* ptr, std::string_view name, const MemberData& data = {});
template<typename R, typename ...Args>
static FieldPtr MethodField(R(*ptr)(Args...), CName name, const MethodData& data = {});
static FieldPtr MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data = {});
template<typename T, typename R, typename ...Args>
static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {});
static FieldPtr MethodField(R(T::* ptr)(Args...), std::string_view name, const MethodData& data = {});
template<typename T, typename R, typename ...Args>
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {}) {
static FieldPtr MethodField(R(T::* ptr)(Args...)const, std::string_view name, const MethodData& data = {}) {
return MethodField(remove_const(ptr), name, data);
}
};

View File

@ -43,7 +43,7 @@ namespace refl {
return FieldPtr{Name("Ctor"), cls, method, flag};
}
template<typename T, typename Obj>
inline FieldPtr MetaHelp::MemberField(T Obj::* ptr, CName name, const MemberData& data)
inline FieldPtr MetaHelp::MemberField(T Obj::* ptr, std::string_view name, const MemberData& data)
{
const UClass* cls = meta_info<T>();
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
@ -58,7 +58,7 @@ namespace refl {
return FieldPtr{ name, cls, member, flag };
}
template<typename R, typename ...Args>
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), CName name, const MethodData& data)
inline FieldPtr MetaHelp::MethodField(R(*ptr)(Args...), std::string_view name, const MethodData& data)
{
MethodData method;
uint32_t flag = FIELD_METHOD_FLAG;
@ -74,7 +74,7 @@ namespace refl {
return { name, cls, method,flag };
}
template<typename T, typename R, typename ...Args>
inline FieldPtr MetaHelp::MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data) {
inline FieldPtr MetaHelp::MethodField(R(T::* ptr)(Args...), std::string_view name, const MethodData& data) {
MethodData method;
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
const UClass* cls = meta_info<real_type_t<R>(*)(const void*, real_type_t<Args>...)>();

View File

@ -1,7 +1,9 @@
#pragma once
#include "pmr/name.h"
#include <array>
#include <string_view>
namespace refl {
using pmr::Name;
template <size_t N>
struct TStr {
std::array<char, N> value{}; // 确切长度的字符数组,不依赖 '\0'
@ -23,8 +25,6 @@ namespace refl {
template <size_t N>
TStr(const char(&)[N]) -> TStr<N - 1>;
template<auto v>
constexpr auto value_name() noexcept;
template<typename T>
constexpr auto meta_name() noexcept;
Name meta_name()noexcept;
}

View File

@ -15,7 +15,7 @@ namespace refl {
# endif
}
template<typename T>
constexpr auto raw_meta_name() noexcept {
constexpr auto raw_meta_tstr() noexcept {
constexpr std::string_view sign = func_signature<T>();
constexpr size_t size = sign.size();
return TStr<size>{ sign };
@ -32,7 +32,7 @@ namespace refl {
return num < 10 ? 1 : 1 + _num_digits(num / 10);
}
template <int N, int Digits = _num_digits(N)>
constexpr auto num_name() {
constexpr auto num_tstr() {
char data[Digits + 1];
int n = N;
for (int i = Digits - 1; i >= 0; --i) {
@ -42,7 +42,7 @@ namespace refl {
return TStr{ data };
}
template<typename T>
constexpr auto num_prefix_name() {
constexpr auto num_prefix_tstr() {
if constexpr (std::is_integral_v<T>) {
if constexpr (std::is_signed_v<T>) {
return TStr{ "S" };
@ -60,7 +60,7 @@ namespace refl {
}
}
template<auto v>
constexpr auto value_name()noexcept {
constexpr auto value_tstr()noexcept {
using T = decltype(v);
if constexpr (std::is_null_pointer_v<T>)
return TStr{ "nullptr" };
@ -95,13 +95,13 @@ namespace refl {
}
}
template<typename T>
constexpr auto meta_name() noexcept {
constexpr auto meta_tstr() noexcept {
if constexpr (std::is_same_v<T, void>) {
return TStr{ "void" };
}
else if constexpr (std::is_arithmetic_v<T>) {
constexpr auto prefix = detail::num_prefix_name<T>();
constexpr auto bit = detail::num_name<8 * sizeof(T)>();
constexpr auto prefix = detail::num_prefix_tstr<T>();
constexpr auto bit = detail::num_tstr<8 * sizeof(T)>();
return concat_seq(prefix, bit);
}
else if constexpr (std::is_array_v<T>) {
@ -109,20 +109,26 @@ namespace refl {
constexpr auto ex = std::extent_v<T, 0>;
if constexpr (r == 1) {
if constexpr (ex == 0)
return concat_seq(TStr{"[]{"}, meta_name<std::remove_extent_t<T>>(), TStr{"}"});
return concat_seq(TStr{"[]{"}, meta_tstr<std::remove_extent_t<T>>(), TStr{"}"});
else
return concat_seq(TStr{"["}, detail::num_name<ex>(), TStr{"]{"}, meta_name<std::remove_extent_t<T>>(), TStr{"}"});
return concat_seq(TStr{"["}, detail::num_tstr<ex>(), TStr{"]{"}, meta_tstr<std::remove_extent_t<T>>(), TStr{"}"});
}
else { // r > 1
static_assert(r > 1);
if constexpr (ex == 0)
return concat_seq(TStr{"[]"}, type_name<std::remove_extent_t<T>>());
else
return concat_seq(TStr{"["}, detail::num_name<ex>(), TStr{"]"}, meta_name<std::remove_extent_t<T>>());
return concat_seq(TStr{"["}, detail::num_tstr<ex>(), TStr{"]"}, meta_tstr<std::remove_extent_t<T>>());
}
}
else {
return detail::raw_meta_name<T>();
return detail::raw_meta_tstr<T>();
}
}
template<typename T>
Name meta_name() noexcept
{
auto view = meta_tstr<T>().view();
return Name(view);
}
}

View File

@ -7,8 +7,6 @@
namespace refl {
using std::span;
using pmr::Name;
using pmr::CName;
using pmr::FName;
using pmr::table;
namespace detail {
// 定义一个模板结构体用于检测是否为 数组

View File

@ -26,11 +26,11 @@ namespace refl {
struct vtable_uclass
{
struct Node {
size_t name;
Name name;
void* method;
Node* next;
Node(size_t name, void* ptr) :name(name), method(ptr), next(nullptr) {}
Node* Insert(size_t name, void* ptr) {
Node(Name name, void* ptr) :name(name), method(ptr), next(nullptr) {}
Node* Insert(Name name, void* ptr) {
Node* it = new Node(name, ptr);
next = it;
return it;
@ -39,9 +39,6 @@ namespace refl {
Node* header{nullptr};
operator bool() { return header; }
void Add(Name name, void* ptr) {
Add(name.Hash(), ptr);
}
void Add(size_t name, void* ptr) {
auto [bfind, it] = FindLast(name);
if (bfind) {
return;
@ -50,7 +47,7 @@ namespace refl {
Node** prev= it ? &(it->next) : &header;
*prev = next;
}
std::pair<bool,Node*> FindLast(size_t name) const{
std::pair<bool,Node*> FindLast(Name name) const{
Node *prev = nullptr, *it = header;
while (it) {
if (it->name == name) {
@ -61,7 +58,7 @@ namespace refl {
}
return std::make_pair(false, prev);
}
void* Find(size_t name) const {
void* Find(Name name) const {
Node* it = header;
while (it) {
if (it->name == name) {
@ -81,25 +78,25 @@ namespace refl {
using Construct_t = bool (*)(void* ptr, const UClass* cls,span<Any> ArgsList);
using Destruct_t = void (*)(void*);
void AddGetFields(GetFields_t func) {
Add(string_hash("GetFields"), (void*)func);
Add(Name("GetFields"), (void*)func);
}
void AddGetParams(GetParams_t func) {
Add(string_hash("GetParams"), (void*)func);
Add(Name("GetParams"), (void*)func);
}
void AddCall(Call_t func) {
Add(string_hash("Call"), (void*)func);
Add(Name("Call"), (void*)func);
}
void AddConstruct(Construct_t func) {
Add(string_hash("Construct"), (void*)func);
Add(Name("Construct"), (void*)func);
}
void AddDestruct(Destruct_t func) {
Add(string_hash("Destruct"), (void*)func);
Add(Name("Destruct"), (void*)func);
}
GetFields_t GetFields() const { return (GetFields_t) Find(string_hash("GetFields")); }
GetParams_t GetParams() const { return (GetParams_t) Find(string_hash("GetParams")); }
Call_t Call() const { return (Call_t) Find(string_hash("Call")); }
Construct_t Construct() const { return (Construct_t) Find(string_hash("Construct")); }
Destruct_t Destruct() const { return (Destruct_t) Find(string_hash("Destruct")); }
GetFields_t GetFields() const { return (GetFields_t) Find(Name("GetFields")); }
GetParams_t GetParams() const { return (GetParams_t) Find(Name("GetParams")); }
Call_t Call() const { return (Call_t) Find(Name("Call")); }
Construct_t Construct() const { return (Construct_t) Find(Name("Construct")); }
Destruct_t Destruct() const { return (Destruct_t) Find(Name("Destruct")); }
};
class UClass {
public:
@ -111,7 +108,7 @@ namespace refl {
UClass(const UClass*) = delete;
UClass& operator=(const UClass*) = delete;
public:
UClass(std::string_view name, uint32_t size, const UClass* parent = nullptr)
UClass(Name name, uint32_t size, const UClass* parent = nullptr)
:name(name), size(size), parent(parent) {}
Any New(pmr::memory_resource* pool, span<Any> ArgsList = {}) const {
void* ptr = pool->allocate(size);

View File

@ -5,7 +5,7 @@ namespace refl {
template<typename T>
class UClass_Auto : public UClass {
public:
UClass_Auto() : UClass(meta_name<T>().view(), sizeof(T)) {
UClass_Auto() : UClass(meta_name<T>(), sizeof(T)) {
if constexpr (std::is_pointer_v<T>) {
using RT = std::remove_pointer_t<T>;
flag |= CLASS_POINTER_FLAG;
@ -38,7 +38,7 @@ namespace refl {
using MethodType = R(*)(Args...);
public:
std::array<const UClass*, sizeof...(Args) + 1> UList{};
UMethod_Auto() : UClass(meta_name<MethodType>().view(), sizeof(MethodType)) {
UMethod_Auto() : UClass(meta_name<MethodType>(), sizeof(MethodType)) {
flag = CLASS_TRIVIAL_FLAG;
vtable.AddGetParams(&UMethod_Auto::GetParams);
vtable.AddCall(&UMethod_Auto::Call);
@ -137,7 +137,7 @@ namespace refl {
memcpy(pit, &it, sizeof(it));
pit->val = &*it;
}
UClass_Container() : UClass_Container_Impl(meta_name<T>().view(), sizeof(T)) {
UClass_Container() : UClass_Container_Impl(meta_name<T>(), sizeof(T)) {
parent = meta_info<value_type>();
flag = CLASS_CONTAINER_FLAG;
vtable.AddConstruct(&UClass_Container::construct);
@ -164,7 +164,7 @@ namespace refl {
using FieldsType = decltype(MetaImpl::MakeFields());
public:
FieldsType Fields{ MetaImpl::MakeFields() };
UClass_Meta() : UClass(meta_name<T>().view(), sizeof(T)) {
UClass_Meta() : UClass(meta_name<T>(), sizeof(T)) {
if constexpr (has_parent_v<T>) {
parent = meta_info<parent_t<T>>();
}
@ -281,8 +281,8 @@ namespace refl {
inline const UClass* meta_info()
{
using T = real_type_t<Type>;
constexpr auto name = meta_name<T>();
if (auto cls = find_info(name.view())) {
auto name = meta_name<T>();
if (auto cls = find_info(name)) {
return cls;
}
UClass* cls;
@ -290,27 +290,27 @@ namespace refl {
cls = new(MetaGlobalPool()) UClass_Meta<T, meta_t<T>>{};
}
else if constexpr (std::is_same_v<T, void>) {
cls = new(MetaGlobalPool()) UClass{ name.view(), 0 };
cls = new(MetaGlobalPool()) UClass{ name, 0 };
}
else {
cls = meta_info_impl<T>::create();
}
auto& ClassTable = UNIQUER_VAL(ClassTable);
ClassTable[name.view()] = cls;
ClassTable[name] = cls;
return cls;
}
template<typename T, size_t hash>
inline const UClass* meta_info()
{
if constexpr (have_meta_impl_v<T, hash>) {
constexpr auto name = meta_name<T>();
const UClass* cls = find_info(name.view(), hash);
auto name = meta_name<T>();
const UClass* cls = find_info(name, hash);
if (cls) {
return cls;
}
cls = new(MetaGlobalPool()) UClass_Meta<T, gen::MetaImpl<T, hash>>{};
auto& MetaClassTable = UNIQUER_VAL(MetaClassTable);
if (auto it = MetaClassTable.find(name.view()); it != MetaClassTable.end()) {
if (auto it = MetaClassTable.find(name); it != MetaClassTable.end()) {
auto meta = &it->second;
while (meta) {
if (!meta->next) {
@ -321,7 +321,7 @@ namespace refl {
}
}
else {
MetaClassTable.emplace(name.view(), MetaClasses{hash, cls});
MetaClassTable.emplace(name, MetaClasses{hash, cls});
}
return cls;
}

View File

@ -6,3 +6,4 @@ header_component("zlib","engine")
end
add_syslinks("kernel32")
set_pcheader("include/refl/pch.h")
add_deps("xmalloc", {public = true})

View File

@ -29,7 +29,7 @@ function shared_module(name, owner, opt)
set_group("Engine/"..owner.."__dyn")
add_rules("engine.api")
add_includedirs("include", {public = true})
--add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
add_rules("engine.plugin", {file = opt and opt.file or "include/" .. name .. "/module.h"})
end
function add_dependency(...)
add_deps(...)

View File

@ -12,7 +12,6 @@ target("engine")
set_group("Engine")
add_rules("engine.api")
add_files("src/engine/*.cpp")
add_deps("xmalloc", {public = true})
includes("xmake/xmake.lua")
includes("3rdparty/xmake.lua")
includes("tools/xmake.lua")