Files
mir_server/sdk/srvlib/include/ObjectAllocator.hpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

178 lines
4.9 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 "ObjectAllocStat.hpp"
#include "Platform.h"
template <typename T>
class CObjectAllocator : public CObjectAllocatorStat
{
public:
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
typedef CObjectAllocatorStat Inherited;
//#endif
//内存块描述结构,用于查询内存块信息
struct DataBlockDesc
{
const char* lpBaseAddress;//内存块指针地址
size_t dwBlockSize; //内存块大小
};
private:
//内存块链表节点
struct DataBlock
{
T* pFreePtr; //指向空闲的对象
T* pEndPtr; //指向对象内存块的结束
DataBlock* pPrev;
} *m_pDataBlock;
public:
enum {
AllocObjectCountOneTime = 1024
};
//申请属性指针
T* allocObjects(const INT_PTR nCount = 1)
{
T* result;
DataBlock *pBlock = m_pDataBlock;
//尝试从当前内存块中申请nCount的对象如果内存块中没有足够的对象则向之前的内存块中查找是否具有足够的空闲对象
if ( !pBlock || pBlock->pEndPtr - pBlock->pFreePtr < nCount )
{
//向之前的内存块中查找是否具有足够的空闲对象
while (pBlock && (pBlock = pBlock->pPrev))
{
if ( pBlock->pEndPtr - pBlock->pFreePtr >= nCount )
break;
}
//如果所有内存块中都没有足够的对象则申请新内存块
if ( pBlock == NULL )
{
INT_PTR nAllocCount = __max(nCount, AllocObjectCountOneTime);
pBlock = (DataBlock*)malloc(sizeof(DataBlock) + sizeof(T) * nAllocCount);
memset(pBlock, 0, sizeof(DataBlock) + sizeof(T) * nAllocCount);
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
m_nAllocObjNum += nAllocCount;
//#endif
pBlock->pFreePtr = (T*)(pBlock + 1);
pBlock->pEndPtr = pBlock->pFreePtr + nAllocCount;
pBlock->pPrev = m_pDataBlock;
m_pDataBlock = pBlock;
}
}
//返回对象指针
result = pBlock->pFreePtr;
pBlock->pFreePtr += nCount;
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
m_nUsedObjNum += nCount;
//#endif
return result;
}
//获取内存块数量
inline INT_PTR blockCount() const
{
INT_PTR result = 0;
DataBlock *pBlock = m_pDataBlock;
while (pBlock)
{
result++;
pBlock = pBlock->pPrev;
}
return result;
}
/*
* Comments: 枚举内存块描述信息
* Param LPCVOID lpEnumKey: 上次枚举的返回值作为枚举下一个的依据第一次枚举此值必须为NULL。
* Param DataBlockDesc & desc: 用于保存内存块描述的对象
* @Return LPCVOID: 返回一个内存块枚举key指针便于进行下次枚举。如果返回值为NULL则表示枚举结束
*
* ★★注意★★:枚举内存块描述的操作是倒叙进行的,第一个被枚举的内存块描述为左后一个内存块的描述!
*
* ★★示例代码★★:-------------------------------------------------
* LPCVOID lpEnumKey = NULL;
* CObjectAllocator<T>::DataBlockDesc desc;
* while (lpEnumKey = allocator.enumBlockDesc(lpEnumKey, desc))
* {
* printf("Memory Block Info { Address = %X, Size = %u }",
* desc.lpBaseAddress, desc.dwBlockSize);
* }
* --------------------------------------------------------------
*/
inline LPCVOID enumBlockDesc(LPCVOID lpEnumKey, DataBlockDesc &desc) const
{
DataBlock *pBlock = (DataBlock*)lpEnumKey;
if (!pBlock)
pBlock = m_pDataBlock;
else pBlock = pBlock->pPrev;
if (pBlock)
{
desc.lpBaseAddress = ((const char*)pBlock) + sizeof(*pBlock);
desc.dwBlockSize = pBlock->pEndPtr - desc.lpBaseAddress;
return pBlock;
}
return NULL;
}
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
CObjectAllocator(LPCTSTR lpszDesc = NULL) : Inherited(sizeof(T), CObjectAllocatorStat::enAT_ObjectAlloc, lpszDesc)
{
m_pDataBlock = NULL;
}
/*
#else
CObjectAllocator(LPCTSTR lpszDesc = NULL)
{
m_pDataBlock = NULL;
}
#endif
*/
~CObjectAllocator()
{
DataBlock *pBlock, *pPrev;
pBlock = m_pDataBlock;
while (pBlock)
{
pPrev = pBlock->pPrev;
free(pBlock);
pBlock = pPrev;
}
m_pDataBlock = NULL;
}
inline CObjectAllocator& operator = (const CObjectAllocator &rhs)
{
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
Inherited::operator=(rhs);
//#endif
m_pDataBlock = rhs.m_pDataBlock;
//#ifdef _ENABLE_OBJ_COUNT_STATICS_
((CObjectAllocatorStat*)(&rhs))->removeFromStat();
Inherited::addToStat();
//#endif
return *this;
}
private:
CObjectAllocator(const CObjectAllocator &rhs);
};