diff --git a/inc/hgl/SourceCodeLocation.h b/inc/hgl/SourceCodeLocation.h new file mode 100644 index 0000000..58d0964 --- /dev/null +++ b/inc/hgl/SourceCodeLocation.h @@ -0,0 +1,14 @@ +#pragma once + +namespace hgl +{ + struct SourceCodeLocation + { + const char * file; ///<源文件 + const char * func; ///<函数 + size_t line; ///<行号 + }; + + #define HGL_SOURCE_CODE_LOCATION __FILE__,__FUNCTION__,__LINE__ + +}//namespace hgl diff --git a/inc/hgl/math/Transform.h b/inc/hgl/math/Transform.h index fc879c3..74acb89 100644 --- a/inc/hgl/math/Transform.h +++ b/inc/hgl/math/Transform.h @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include diff --git a/inc/hgl/type/TypeInfo.h b/inc/hgl/type/TypeInfo.h new file mode 100644 index 0000000..de974ad --- /dev/null +++ b/inc/hgl/type/TypeInfo.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace hgl +{ + template inline constexpr const size_t GetTypeHash()noexcept{return typeid(T).hash_code();} ///<取得一个类型的哈希值 + template inline constexpr const char * GetTypeName()noexcept{return typeid(T).name();} ///<取得一个类型的名称 +}//namespace hgl diff --git a/inc/hgl/type/object/DefaultCreateObject.h b/inc/hgl/type/object/DefaultCreateObject.h new file mode 100644 index 0000000..dc8d67c --- /dev/null +++ b/inc/hgl/type/object/DefaultCreateObject.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace hgl +{ + template SafePtr DefaultCreateObject(const char *source_file,const char *source_function,const size_t source_line,ARGS...args) + { + const size_t hc=GetTypeHash(); + + ObjectManager *om=GetObjectManager(hc); + + if(!om) + return SafePtr(); + + DefaultObjectManager *dom=static_cast *>(om); + + const SourceCodeLocation scl + { + .file=source_file, + .func=source_function, + .line=source_line + }; + + SafePtrData *spd=dom->CreateObject(scl,args...); + + return SafePtr(spd); + } + + #define HGL_NEW_OBJECT(class_name,...) DefaultCreateObject(__FILE__,__FUNCTION__,__LINE__ __VA_OPT__(,) __VA_ARGS__) + + #define HGL_DEFINE_OBJECT(class_name,type_name,...) SafePtr type_name=HGL_NEW_OBJECT(class_name __VA_OPT__(,) __VA_ARGS__) +}//namespace hgl + diff --git a/inc/hgl/type/object/Object.h b/inc/hgl/type/object/Object.h new file mode 100644 index 0000000..b391a92 --- /dev/null +++ b/inc/hgl/type/object/Object.h @@ -0,0 +1,228 @@ +#pragma once +#include + +namespace hgl +{ + /** + * 基础对象. + */ + class Object + { + ObjectBaseInfo object_base_info; + + public: + + const ObjectBaseInfo & GetObjectBaseInfo () const noexcept { return object_base_info; } ///<获取对象基本信息 + + ObjectManager * GetObjectManager () noexcept { return object_base_info.object_manager; } ///<获取对象管理器 + + const size_t GetHashCode () const noexcept { return object_base_info.hash_code; } ///<获取对象数据类型的hash值 + const size_t GetSerialNumber () const noexcept { return object_base_info.serial_number; } ///<获取对象的序列号 + + protected: + + template friend class SafePtr; + template friend struct DefaultObjectAllocator; + + Object(const ObjectBaseInfo &obi) noexcept { object_base_info=obi; } + virtual ~Object()=default; + + virtual void Deinitailize()=0; + };//class Object + + template class DefaultObjectManager; + + #define HGL_OBJECT_CLASS_BODY(class_name) \ + private: \ + \ + friend struct DefaultObjectAllocator;\ + \ + class_name(const ObjectBaseInfo &obi):Object(obi)=default; \ + /*{std::cout<<#class_name " Construct("<();} \ + + + + template struct SafePtrData + { + T *ptr; + int count; + + private: + + SafePtrData(T *p) + { + ptr=p; + count=0; + } + + ~SafePtrData()=default; + + template friend class DefaultObjectManager; + }; + + /** + * 安全访问指针
+ * 其本质类似于的WeakPtr,但是不同的是: + *
    + *
  • SafePtr不使用atom计数器,所以它不是线程安全的
  • + *
  • SafePtr不会自动释放指针,它是在访问时检查指针是否有效,如果无效则返回nullptr
  • + *
+ */ + template class SafePtr + { + SafePtrData *data; + + public: + + SafePtr() + { + data=nullptr; + } + + SafePtr(SafePtrData *spd) + { + data=spd; + + if(data) + ++data->count; + } + + public: + + virtual ~SafePtr() + { + Release(); + } + + T *Get() {return data?data->ptr:nullptr;} + const T *Get() const {return data?data->ptr:nullptr;} + + T *operator->() { return Get(); } + T &operator* () { return *Get(); } + + const T *operator->() const { return Get(); } + + const bool operator==(const T *ptr) const noexcept { return Get()==ptr; } + const bool operator!=(const T *ptr) const noexcept { return Get()!=ptr; } + + const bool operator==(const SafePtr &sp) const { return Get()==sp.Get(); } + const bool operator!=(const SafePtr &sp) const { return Get()!=sp.Get(); } + + const bool IsValid() const noexcept ///<当前对象指针是否有效 + { + return data&&data->ptr; + } + + SafePtr &operator=(SafePtr &sp) + { + if(!sp.IsValid()) + { + Release(); + return *this; + } + + if(data) + { + if(data->ptr==sp.data->ptr) + return *this; + + Release(); + } + + data=sp.data; + ++data->count; + + return *this; + } + + template + SafePtr &operator=(SafePtr &spd) + { + if(T::StaticHashCode()!=OT.StaticHashCode()) + { + Release(); + return *this; + } + + if(data!=spd.data) + { + Release(); + data=spd.data; + ++data->count; + } + + return *this; + } + + SafePtr &operator=(Object *obj)=delete; + + /** + * 强制释放对象(不管所有权问题,强制释放) + */ + void Destory() + { + if(!data) + return; + + if(!data->ptr) + return; + + ObjectManager *om=data->ptr->GetObjectManager(); + + if(!om) + { + //std::cerr<<"SafePtr<"<()<<">::Destory() error, manager is null."<()<<">::Destory() serial:"<ptr->GetSerialNumber()< *dom=static_cast *>(om); + + dom->ReleaseObject(data); + + data=nullptr; + } + + /** + * 释放对象(释放所有权,不代表会被释放。当所有权计数为0时会被释放) + * + * \return 依然持有对象的数量 + */ + int Release() + { + if(!data) + return -1; + + //if(data->ptr) + //{ + // std::cout<<"SafePtr<"<()<<">::Release() serial:"<ptr->GetSerialNumber()<count==1) + { + Destory(); + result=0; + } + else + { + --data->count; + + result=data->count; + } + + data=nullptr; + return result; + } + };//template class SafePtr +}//namespace hgl + diff --git a/inc/hgl/type/object/ObjectAllocator.h b/inc/hgl/type/object/ObjectAllocator.h new file mode 100644 index 0000000..c72198e --- /dev/null +++ b/inc/hgl/type/object/ObjectAllocator.h @@ -0,0 +1,60 @@ +#pragma once +//#include + +namespace hgl +{ + struct ObjectBaseInfo; + class Object; + class ObjectManager; + + /** + * 对象分配器. + */ + struct ObjectAllocator + { + virtual void Join (ObjectManager *) {}; ///<桥接一个对象管理器 + virtual void Unjoin (ObjectManager *) {}; ///<断开一个对象管理器 + + virtual Object *Create (const ObjectBaseInfo &obi)=0; ///<创建一个新对象 + virtual void Release (Object *)=0; ///<释放一个对象 + + /** + * 准备断开对象管理器 + * @param not_release_objects_count 未释放的对象数量 + * @return 是否需要逐个释放(如返回true则会调用CleanNotReleaseObject逐个释放) + */ + virtual bool PreUnjoin(int not_release_objects_count) + { + //std::cerr<<"DefaultObjectManager::~DefaultObjectManager("<GetObjectBaseInfo(); + + //std::cout<<"Object(hash_code="< struct DefaultObjectAllocator:public ObjectAllocator + { + virtual Object *Create(const ObjectBaseInfo &obi)override + { + return new T(obi); + } + + virtual void Release(Object *obj)override + { + delete obj; + } + }; +}//namespace hgl + diff --git a/inc/hgl/type/object/ObjectBaseInfo.h b/inc/hgl/type/object/ObjectBaseInfo.h new file mode 100644 index 0000000..2879a92 --- /dev/null +++ b/inc/hgl/type/object/ObjectBaseInfo.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace hgl +{ + class ObjectManager; + + struct ObjectBaseInfo + { + size_t hash_code; ///<对象数据类型的hash值 + ObjectManager * object_manager; ///<对象管理器 + size_t serial_number; ///<对象序列号 + + SourceCodeLocation source_code_location; + }; +}//namespace hgl + diff --git a/inc/hgl/type/object/ObjectManager.h b/inc/hgl/type/object/ObjectManager.h new file mode 100644 index 0000000..555559c --- /dev/null +++ b/inc/hgl/type/object/ObjectManager.h @@ -0,0 +1,169 @@ +#pragma once +#include"Object.h" +#include"ObjectAllocator.h" +#include +#include + +namespace hgl +{ + class Object; + + /** + * 对象管理器基类. + */ + class ObjectManager + { + size_t object_hash_code; + const char *object_type_name; + size_t object_count; + + protected: + + const size_t AcquireSerialNumber(){return ++object_count;} + + public: + + const size_t GetHashCode()const{return object_hash_code;} + const char * GetTypename()const{return object_type_name;} + const size_t GetCount()const{return object_count;} + + public: + + ObjectManager(const size_t &hc,const char *tn) + { + object_hash_code=hc; + object_type_name=tn; + object_count=0; + } + + virtual ~ObjectManager()=default; + };//class ObjectManager + + bool RegistryObjectManager(ObjectManager *om); ///<注册一个对象管理器 + void UnregistryObjectManager(ObjectManager *om); ///<注销一个对象管理器 + + /** + * 缺省对象管理器 + */ + template class DefaultObjectManager:public ObjectManager + { + tsl::robin_set object_set; + tsl::robin_map *> object_map; + + ObjectAllocator *object_allocator; + + public: + + DefaultObjectManager(ObjectAllocator *oa):ObjectManager(typeid(T).hash_code(),typeid(T).name()) + { + object_allocator=oa; + + object_allocator->Join(this); + RegistryObjectManager(this); + } + + virtual ~DefaultObjectManager() + { + if(object_set.size()) + { + if(object_allocator->PreUnjoin(object_set.size())) //这里返回的是是否需要逐个释放 + { + for(auto &it:object_set) + { + object_allocator->CleanNotReleaseObject(it); + } + } + } + + object_allocator->Unjoin(this); + UnregistryObjectManager(this); + } + + protected: + + template friend SafePtr DefaultCreateObject(const char *source_file,const char *source_function,const size_t source_line,ARGS...args); + + template + SafePtrData *CreateObject(const SourceCodeLocation &scl,ARGS...args) + { + ObjectBaseInfo obi + { + .hash_code =GetHashCode(), + .object_manager =this, + .serial_number =AcquireSerialNumber(), + .source_code_location=scl + }; + + Object *obj=object_allocator->Create(obi); + + SafePtrData *spd=new SafePtrData((T *)obj); + + object_set.insert({(T *)obj}); + object_map.insert({obj->GetSerialNumber(),spd}); + + spd->ptr->Initailize(args...); + + return spd; + } + + template friend class SafePtr; + + void ReleaseObject(SafePtrData *spd) + { + if(!spd) + return; + + object_map.erase(spd->ptr->GetSerialNumber()); + object_set.erase(spd->ptr); + + if(spd->ptr) + { + spd->ptr->Deinitailize(); + object_allocator->Release(spd->ptr); + spd->ptr=nullptr; + } + + if(spd->count>1) + { + --spd->count; + } + else + { + delete spd; + } + } + + template friend SafePtr GetObjectBySerial(const size_t &serial); + + SafePtrData *GetObjectBySerial(const size_t &serial) + { + return object_map.at(serial); + } + };//class DefaultObjectManager + + #define HGL_DEFINE_DEFAULT_OBJECT_MANAGER(T) namespace \ + { \ + static DefaultObjectAllocator T##ObjectAllocator; \ + static DefaultObjectManager T##ObjectManager(&T##ObjectAllocator); \ + } + + ObjectManager *GetObjectManager(const size_t &hash_code); ///<取得一个对象管理器 + + template inline ObjectManager *GetObjectManager() ///<取得一个对象管理器 + { + return GetObjectManager(typeid(T).hash_code()); + } + + template inline SafePtr GetObjectBySerial(const size_t &serial) ///<通过序列号取得一个对象 + { + ObjectManager *om=GetObjectManager(); + + if(!om) + return SafePtr(); + + DefaultObjectManager *dom=static_cast *>(om); + + return SafePtr(dom->GetObjectBySerial(serial)); + } +}//namespace hgl + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1858080..84f86b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,10 @@ SET(CORE_PLATFORM_HEADER_FILES ${CORE_PLATFORM_HEADER_FILES} ${CORE_PLATFORM_OS_FILES} ${CORE_PLATFORM_COMPILER_FILES}) +SET(TYPE_INFO_FILE ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/TypeInfo.h) + +SOURCE_GROUP("DataType" FILES ${TYPE_INFO_FILE}) + SET(TYPE_INCLUDE_PATH ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type) SET(TYPE_IDNAME_HEADER_FILES ${TYPE_INCLUDE_PATH}/ConstStringSet.h @@ -48,9 +52,18 @@ SET(SYSTEM_INFO_SOURCE ${CORE_PLATFORM_INCLUDE_PATH}/SystemInfo.h SET(MATH_INCLUDE_PATH ${CMCORE_ROOT_INCLUDE_PATH}/hgl/math) -SET(BASE_OBJECT_SOURCE_FILES Object/TickObject.cpp) +SET(BASE_OBJECT_HEADER_FILES ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/object/ObjectBaseInfo.h + ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/object/Object.h + ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/object/ObjectAllocator.h + ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/object/ObjectManager.h + ${CMCORE_ROOT_INCLUDE_PATH}/hgl/type/object/DefaultCreateObject.h) -SOURCE_GROUP("DataType\\Object" FILES ${BASE_OBJECT_SOURCE_FILES}) +SET(BASE_OBJECT_SOURCE_FILES Object/Object.cpp + Object/ObjectManager.cpp + Object/TickObject.cpp) + +SOURCE_GROUP("DataType\\Object" FILES ${BASE_OBJECT_HEADER_FILES} + ${BASE_OBJECT_SOURCE_FILES}) ##Math-------------------------------------------------------- SET(MATH_HEADER_FILES ${MATH_INCLUDE_PATH}/bvec.h @@ -237,6 +250,8 @@ SOURCE_GROUP("Log\\Source Files" FILES ${BASE_LOG_SOURCE}) add_cm_library(CMCore "CM" ${CORE_PLATFORM_HEADER_FILES} #${SYSTEM_INFO_SOURCE} + ${TYPE_INFO_FILE} + ${BASE_OBJECT_HEADER_FILES} ${BASE_OBJECT_SOURCE_FILES} ${COLOR_HEADER_FILES} diff --git a/src/Object/Object.cpp b/src/Object/Object.cpp new file mode 100644 index 0000000..046c02c --- /dev/null +++ b/src/Object/Object.cpp @@ -0,0 +1,16 @@ +//#include + +namespace hgl +{ + //Object::Object(const ObjectBaseInfo &obi) noexcept + //{ + // object_base_info=obi; + + // std::cout<<"Object Construct("< +//#include +//#include +#include + +namespace hgl +{ + namespace + { + using ObjectManagerMap=tsl::robin_map; + static ObjectManagerMap *object_manager_map=nullptr; + + ObjectManagerMap *GetObjectManagerMap() + { + if(!object_manager_map) + object_manager_map=new ObjectManagerMap; + + return(object_manager_map); + } + }//namespace + + bool RegistryObjectManager(ObjectManager *om) + { + if(!om) + return(false); + + const size_t hc=om->GetHashCode(); + + auto *omm=GetObjectManagerMap(); + + if(omm->contains(hc)) + return(false); + + omm->insert({hc,om}); + + //std::cout<<"RegistryObjectManager("<GetTypename()<<")"<GetHashCode(); + + auto *omm=GetObjectManagerMap(); + + auto omi=omm->find(hc); + + if(omi.key()!=hc) + return; + + //std::cout<<"UnregistryObjectManager("<GetTypename()<<")"<erase(hc); + } + + ObjectManager *GetObjectManager(const size_t &hash_code) + { + auto *omm=GetObjectManagerMap(); + + auto omi=omm->find(hash_code); + + if(omi.key()==hash_code) + return(omi.value()); + else + return(nullptr); + } +}//namespace hgl