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

173 lines
4.4 KiB
C++
Raw Permalink 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.

#ifndef _BUFF_ALLOCATOR_H_
#define _BUFF_ALLOCATOR_H_
/************************************************************************
* 一次性的内存分配器
* 适用于一次分配内存后,直到程序结束才释放内存的地方,如配置文件的读取
* 用这个分配器的好处是:不提供释放内存的函数,因此不需要一个个内存手工释放,
* 而是由分配器一次释放
************************************************************************/
#include "os_def.h"
#include "memory_counter.hpp"
template <typename T, int ONE_TIME_COUNT = 1024>
class MemoryContainer : public AllocatorCounterItem
{
public:
typedef AllocatorCounterItem Inherited;
//内存块描述结构,用于查询内存块信息
struct DataBlockDesc
{
const char* addr;//内存块指针地址
size_t block_size; //内存块大小
};
private:
//内存块链表节点
struct DataBlock
{
T* free_ptr; //指向空闲的对象
T* end_ptr; //指向对象内存块的结束
DataBlock* prev;
} *data_block_;
public:
#ifndef _MEMORY_TRACE_
T* AllocBuffer(size_t count)
#else
T* _AllocBuffer(size_t count, const char*, int)
#endif
{
T* result;
DataBlock *block_ptr = data_block_;
//尝试从当前内存块中申请nCount的对象如果内存块中没有足够的对象则向之前的内存块中查找是否具有足够的空闲对象
if ( !block_ptr || size_t(block_ptr->end_ptr - block_ptr->free_ptr) < count )
{
//向之前的内存块中查找是否具有足够的空闲对象
while (block_ptr && (block_ptr = block_ptr->prev))
{
if ( size_t(block_ptr->end_ptr - block_ptr->free_ptr) >= count )
break;
}
//如果所有内存块中都没有足够的对象则申请新内存块
if ( block_ptr == NULL )
{
size_t alloc_count = __max(count, ONE_TIME_COUNT);
block_ptr = (DataBlock*)malloc(sizeof(DataBlock) + sizeof(T) * alloc_count);
memset(block_ptr, 0, sizeof(DataBlock) + sizeof(T) * alloc_count);
#ifdef _MEMORY_TRACE_
alloc_total_ += alloc_count;
#endif
block_ptr->free_ptr = (T*)(block_ptr + 1);
block_ptr->end_ptr = block_ptr->free_ptr + alloc_count;
block_ptr->prev = data_block_;
data_block_ = block_ptr;
}
}
//返回对象指针
result = block_ptr->free_ptr;
block_ptr->free_ptr += count;
#ifdef _MEMORY_TRACE_
used_count_ += count;
#endif
return result;
}
void _FreeBuffer()
{
DataBlock *block_ptr, *prev;
block_ptr = data_block_;
while (block_ptr)
{
prev = block_ptr->prev;
free(block_ptr);
block_ptr = prev;
}
data_block_ = NULL;
}
//获取内存块数量
inline int blockCount() const
{
int result = 0;
DataBlock *block_ptr = data_block_;
while (block_ptr)
{
result++;
block_ptr = block_ptr->prev;
}
return result;
}
/*
* Comments: 枚举内存块描述信息
* Param LPCVOID lpEnumKey: 上次枚举的返回值作为枚举下一个的依据第一次枚举此值必须为NULL。
* Param DataBlockDesc & desc: 用于保存内存块描述的对象
* @Return LPCVOID: 返回一个内存块枚举key指针便于进行下次枚举。如果返回值为NULL则表示枚举结束
*
* ★★注意★★:枚举内存块描述的操作是倒叙进行的,第一个被枚举的内存块描述为左后一个内存块的描述!
*
* ★★示例代码★★:-------------------------------------------------
* LPCVOID lpEnumKey = NULL;
* BuffAllocator<T>::DataBlockDesc desc;
* while (lpEnumKey = allocator.enumBlockDesc(lpEnumKey, desc))
* {
* printf("Memory Block Info { Address = %X, Size = %u }",
* desc.lpBaseAddress, desc.dwBlockSize);
* }
* --------------------------------------------------------------
*/
inline void* enumBlockDesc(void* enum_key, DataBlockDesc &desc) const
{
DataBlock *block_ptr = (DataBlock*)enum_key;
if (!block_ptr)
block_ptr = data_block_;
else block_ptr = block_ptr->prev;
if (block_ptr)
{
desc.addr = ((const char*)block_ptr) + sizeof(*block_ptr);
desc.block_size = block_ptr->end_ptr - desc.addr;
return block_ptr;
}
return NULL;
}
MemoryContainer(const char* namestr) : Inherited(namestr)
{
data_block_ = NULL;
}
virtual ~MemoryContainer()
{
DataBlock *block_ptr, *prev;
block_ptr = data_block_;
while (block_ptr)
{
prev = block_ptr->prev;
free(block_ptr);
block_ptr = prev;
}
data_block_ = NULL;
MemoryCounter::getSingleton().unregist((AllocatorCounterItem*)this);
}
inline MemoryContainer& operator = (const MemoryContainer &rhs)
{
Inherited::operator=(rhs);
data_block_ = rhs.data_block_;
return *this;
}
//public:
//#ifdef _MEMORY_TRACE_
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
//#endif
private:
MemoryContainer(const MemoryContainer &rhs);
};
#endif //end _BUFF_ALLOCATOR_H_