init
This commit is contained in:
63
Gateway/srvlib/include/memory/align_allocator.h
Normal file
63
Gateway/srvlib/include/memory/align_allocator.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef _ALIGN_ALLOCATOR_H_
|
||||
#define _ALIGN_ALLOCATOR_H_
|
||||
|
||||
/************************************************************************
|
||||
* 适用于小内存的频繁分配的场景,同时为了性能牺牲了部分内存空间
|
||||
************************************************************************/
|
||||
|
||||
using namespace lock;
|
||||
|
||||
#define GetAlignIdx(t) (t % align_ == 0 ? (t / align_ - 1) : (t / align_))
|
||||
|
||||
class AlignAllocator : public BaseAllocator
|
||||
{
|
||||
struct FreeNode
|
||||
{
|
||||
FreeNode* next_;
|
||||
int size_;
|
||||
};
|
||||
|
||||
struct Header
|
||||
{
|
||||
FreeNode* first_;
|
||||
int total_;
|
||||
int free_;
|
||||
Header()
|
||||
{
|
||||
total_ = free_ = 0;
|
||||
first_ = NULL;
|
||||
}
|
||||
};
|
||||
public:
|
||||
AlignAllocator(const char* name, int max_size, int align);
|
||||
virtual ~AlignAllocator();
|
||||
|
||||
public:
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void* AllocBuffer(size_t count);
|
||||
virtual void* ReAllocBuffer(void* src, size_t count);
|
||||
virtual void FreeBuffer(void* ptr);
|
||||
#else
|
||||
virtual void* _AllocBuffer(size_t count, const char*, int);
|
||||
virtual void* _ReAllocBuffer(void* src, size_t newsize, const char* fn, int line);
|
||||
virtual void _FreeBuffer(void* ptr, const char*, int);
|
||||
#endif
|
||||
|
||||
void Init(int max_size, int align);
|
||||
void GC();
|
||||
void SetMultiThread(bool flag) { mult_thread_ = flag; }
|
||||
void SetGCRest(int rest) { rest_ = rest; }
|
||||
|
||||
private:
|
||||
int max_size_;
|
||||
int align_;
|
||||
Header* heads_;
|
||||
int hdrCnt_;
|
||||
int rest_;
|
||||
|
||||
// 支持加锁,可以多线程安全
|
||||
bool mult_thread_;
|
||||
Mutex buffer_lock_;
|
||||
};
|
||||
|
||||
#endif //end _ALIGN_ALLOCATOR_H_
|
||||
54
Gateway/srvlib/include/memory/allocator.hpp
Normal file
54
Gateway/srvlib/include/memory/allocator.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef _BASE_ALLOCATOR_H_
|
||||
#define _BASE_ALLOCATOR_H_
|
||||
|
||||
/************************************************************************
|
||||
* 内存分配器的基类,其他分配器可继承其接口,实现不同的内存分配算法
|
||||
*
|
||||
*
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
#include "memory_counter.hpp"
|
||||
|
||||
class BaseAllocator : public AllocatorCounterItem
|
||||
{
|
||||
public:
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void* AllocBuff(size_t count)
|
||||
#else
|
||||
#define AllocBuff(count_) _AllocBuff(count_,__FILE__, __LINE__)
|
||||
#define FreeBuff(ptr) _FreeBuff(ptr, __FILE__, __LINE__)
|
||||
virtual void* _AllocBuff(size_t count,const char* lpFile, int nLine)
|
||||
#endif
|
||||
{
|
||||
void* result = malloc(count);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
if (result != NULL)
|
||||
{
|
||||
used_count_ += count;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void FreeBuff(void* ptr)
|
||||
#else
|
||||
virtual void _FreeBuff(void* ptr,const char* lpFile, int nLine)
|
||||
#endif
|
||||
{
|
||||
if (ptr) free(ptr);
|
||||
}
|
||||
BaseAllocator(const char* namestr) : AllocatorCounterItem(namestr)
|
||||
{
|
||||
}
|
||||
virtual ~BaseAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
//public:
|
||||
//#ifdef _MEMORY_TRACE_
|
||||
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
|
||||
//#endif
|
||||
};
|
||||
|
||||
#endif //end _BASE_ALLOCATOR_H_
|
||||
23
Gateway/srvlib/include/memory/allocdef.h
Normal file
23
Gateway/srvlib/include/memory/allocdef.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _ALLOCDEF_H_
|
||||
#define _ALLOCDEF_H_
|
||||
|
||||
#include "os_def.h"
|
||||
/************************************************************************
|
||||
* 内存分配的头文件定义
|
||||
*
|
||||
*
|
||||
************************************************************************/
|
||||
#ifdef _MEMORY_TRACE_
|
||||
typedef struct
|
||||
{
|
||||
size_t buff_size_;
|
||||
struct
|
||||
{
|
||||
const char* fn_; //申请内存块的代码位置,用于调试
|
||||
int line_;
|
||||
} al_, fl_;
|
||||
bool using_flag_;
|
||||
} AllocBuffHead;
|
||||
#endif
|
||||
|
||||
#endif //end _ALLOCDEF_H_
|
||||
90
Gateway/srvlib/include/memory/base_allocator.hpp
Normal file
90
Gateway/srvlib/include/memory/base_allocator.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef _BASE_ALLOCATOR_H_
|
||||
#define _BASE_ALLOCATOR_H_
|
||||
|
||||
/************************************************************************
|
||||
* 内存分配器的基类,其他分配器可继承其接口,实现不同的内存分配算法
|
||||
* 这个基类实现的内存分配就是直接用crt分配内存
|
||||
************************************************************************/
|
||||
|
||||
#include "os_def.h"
|
||||
|
||||
#include "memory_counter.hpp"
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
#define AllocBuffer(count_) _AllocBuffer(count_,__FILE__, __LINE__)
|
||||
#define ReAllocBuffer(src,count_) _ReAllocBuffer(src,count_,__FILE__, __LINE__)
|
||||
#define FreeBuffer(ptr) _FreeBuffer(ptr, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
class BaseAllocator : public AllocatorCounterItem
|
||||
{
|
||||
public:
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void* AllocBuffer(size_t count)
|
||||
#else
|
||||
virtual void* _AllocBuffer(size_t count, const char*, int)
|
||||
#endif
|
||||
{
|
||||
size_t* result = (size_t*)malloc(count + sizeof(size_t));
|
||||
#ifdef _MEMORY_TRACE_
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
alloc_total_ += count;
|
||||
|
||||
*result = count;
|
||||
}
|
||||
|
||||
#endif
|
||||
return (void*)(result + 1);
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void* ReAllocBuffer(void* src, size_t count)
|
||||
#else
|
||||
virtual void* _ReAllocBuffer(void* src, size_t count, const char*, int)
|
||||
#endif
|
||||
{
|
||||
#ifdef _MEMORY_TRACE_
|
||||
if (src)
|
||||
{
|
||||
size_t old = *((size_t*)src - 1);
|
||||
alloc_total_ -= old;
|
||||
src = (void*)((size_t*)src - 1);
|
||||
}
|
||||
alloc_total_ += count; // 注意是size_t类型
|
||||
#endif
|
||||
|
||||
size_t* result = (size_t*)realloc(src, count + sizeof(size_t));
|
||||
*result = count;
|
||||
return (void*)(result + 1);
|
||||
}
|
||||
#ifndef _MEMORY_TRACE_
|
||||
virtual void FreeBuffer(void* ptr)
|
||||
#else
|
||||
virtual void _FreeBuffer(void* ptr, const char*, int)
|
||||
#endif
|
||||
{
|
||||
if (!ptr) return;
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
size_t old = *((size_t*)ptr - 1);
|
||||
alloc_total_ -= old;
|
||||
#endif
|
||||
free((size_t*)ptr - 1);
|
||||
}
|
||||
BaseAllocator(const char* namestr) : AllocatorCounterItem(namestr)
|
||||
{
|
||||
}
|
||||
virtual ~BaseAllocator()
|
||||
{
|
||||
}
|
||||
|
||||
void SetMultiThread(bool){}
|
||||
void GC()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif //end _BASE_ALLOCATOR_H_
|
||||
94
Gateway/srvlib/include/memory/buffer_allocator.h
Normal file
94
Gateway/srvlib/include/memory/buffer_allocator.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#ifndef _MSG_ALLOCATOR_H_
|
||||
#define _MSG_ALLOCATOR_H_
|
||||
|
||||
#include "os_def.h"
|
||||
#include "x_tick.h"
|
||||
#include "base_allocator.hpp"
|
||||
#include "x_lock.h"
|
||||
|
||||
class BaseAllocator;
|
||||
|
||||
using namespace tick64;
|
||||
using namespace lock;
|
||||
|
||||
class BufferAllocator: public BaseAllocator
|
||||
{
|
||||
|
||||
public:
|
||||
static const unsigned int SmallBufferSize = 64; //小块内存块大小
|
||||
static const unsigned int MiddleBufferSize = 256; //中等内存块大小
|
||||
static const unsigned int LargeBufferSize = 1024; //大块内存块大小
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct tagBuffer
|
||||
{
|
||||
size_t size_; //内存数据段大小
|
||||
tagBuffer* prev_buffer_;//指向上一个内存块的指针
|
||||
int64_t free_tick_; //即将被销毁的时间
|
||||
#ifdef _MEMORY_TRACE_
|
||||
tagBuffer* next_buffer_;//指向上下个内存块的指针,用于调试
|
||||
struct
|
||||
{
|
||||
const char* fn_; //申请内存块的代码位置,用于调试
|
||||
int line_;
|
||||
} al, fl;
|
||||
bool used_flag_; //是否使用的标记
|
||||
#endif
|
||||
} BUFFER, *PBUFFER;
|
||||
#pragma pack(pop)
|
||||
|
||||
struct BufferStatic
|
||||
{
|
||||
size_t alloc_size_;
|
||||
size_t free_size_;
|
||||
};
|
||||
|
||||
typedef struct tagAllocatorMemoryInfo
|
||||
{
|
||||
BufferStatic SmallBuffer;
|
||||
BufferStatic MiddleBuffer;
|
||||
BufferStatic LargeBuffer;
|
||||
BufferStatic SuperBuffer;
|
||||
} ALLOCATOR_MEMORY_INFO;
|
||||
|
||||
private:
|
||||
Mutex buffer_lock_; //内存块申请锁
|
||||
PBUFFER last_small_buffer_; //指向最后一个空闲的小型内存块的指针
|
||||
PBUFFER last_middle_buffer_; //指向最后一个空闲的中型内存块的指针
|
||||
PBUFFER last_large_buffer_; //指向最后一个空闲的大型内存块的指针
|
||||
PBUFFER last_super_buffer_; //指向最后一个空闲的超级内存块的指针
|
||||
#ifdef _MEMORY_TRACE_
|
||||
PBUFFER last_alloced_buffer_; //指向最后一个被申请的内存块
|
||||
#endif
|
||||
size_t alloced_small_size_; //已被申请的小型内存块大小
|
||||
size_t alloced_middle_size_; //已被申请的中型内存块大小
|
||||
size_t alloced_large_size_; //已被申请的大型内存块大小
|
||||
size_t alloced_super_size_; //已被申请的超级内存块大小
|
||||
size_t freed_small_size_; //已被释放的小型内存块大小
|
||||
size_t freed_middle_size_; //已被释放的中型内存块大小
|
||||
size_t freed_large_size_; //已被释放的大型内存块大小
|
||||
size_t freed_super_size_; //已被释放的超级内存块大小
|
||||
|
||||
bool mult_thread_;
|
||||
public:
|
||||
BufferAllocator(const char* namestr);
|
||||
~BufferAllocator();
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void* AllocBuffer(size_t size);
|
||||
void* ReAllocBuffer(void* ptr, size_t new_size);
|
||||
void FreeBuffer(void* ptr);
|
||||
#else
|
||||
void* _AllocBuffer(size_t size, const char* fn, int line);
|
||||
void* _ReAllocBuffer(void* ptr, size_t new_size, const char* fn, int line);
|
||||
void _FreeBuffer(void* ptr, const char* fn, int line);
|
||||
#endif
|
||||
|
||||
void GetMemoryInfo(BufferAllocator::ALLOCATOR_MEMORY_INFO* pMemoryInfo);
|
||||
void CheckFreeBuffers();
|
||||
void SetMultiThread(bool flag);
|
||||
void GC();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
463
Gateway/srvlib/include/memory/handle_mgr.h
Normal file
463
Gateway/srvlib/include/memory/handle_mgr.h
Normal file
@@ -0,0 +1,463 @@
|
||||
#ifndef _HANDLE_MGR_H_
|
||||
#define _HANDLE_MGR_H_
|
||||
|
||||
#include "os_def.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace memory
|
||||
{
|
||||
|
||||
//template <typename TAG>
|
||||
class Handle
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int index_ : 21; // index into resource array 资源数组的索引
|
||||
unsigned int magic_ : 11; // magic number to check 需要检查的魔术数
|
||||
};
|
||||
unsigned int handle_;
|
||||
};
|
||||
|
||||
public:
|
||||
const static int MAX_INDEX = (1 << 21) - 1;
|
||||
const static int MAX_MAGIC = (1 << 11) - 1;
|
||||
Handle(void) : handle_(0) { }
|
||||
Handle(unsigned int handle)
|
||||
{
|
||||
handle_ = handle ; //
|
||||
}
|
||||
|
||||
void Init(unsigned int index)
|
||||
{
|
||||
assert(index <= (unsigned int)MAX_INDEX);
|
||||
index_ = index;
|
||||
magic_ = wrand(MAX_MAGIC) + 1; //magic_不能等于0,否则可能handle==0
|
||||
}
|
||||
|
||||
inline void Update()
|
||||
{
|
||||
++magic_;
|
||||
|
||||
if (handle_ == 0) ++magic_;
|
||||
}
|
||||
|
||||
inline bool IsNull(void) const
|
||||
{
|
||||
return (!handle_);
|
||||
}
|
||||
inline unsigned int GetIndex(void) const
|
||||
{
|
||||
return (index_);
|
||||
}
|
||||
inline unsigned int GetHandle(void) const
|
||||
{
|
||||
return (handle_);
|
||||
}
|
||||
inline static unsigned int GetMaxIndex()
|
||||
{
|
||||
return MAX_INDEX;
|
||||
}
|
||||
operator unsigned int (void) const
|
||||
{
|
||||
return (handle_);
|
||||
}
|
||||
inline Handle& operator = (const unsigned int h)
|
||||
{
|
||||
handle_ = h;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//一个64位的handle值,支持更大的索引值和魔术数,应用到需要分配更大内存的地方
|
||||
//template <typename TAG>
|
||||
class Handle64
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int index_ : 32; // index into resource array 资源数组的索引
|
||||
unsigned short magic_ : 16; // magic number to check 需要检查的魔术数
|
||||
unsigned short rev_ : 16;
|
||||
};
|
||||
int64_t handle_;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Handle64(void) : handle_(0) { }
|
||||
Handle64(int64_t nHandle)
|
||||
{
|
||||
handle_ = nHandle ; //
|
||||
}
|
||||
|
||||
void Init(unsigned int index)
|
||||
{
|
||||
assert(index <= GetMaxIndex());
|
||||
|
||||
index_ = index;
|
||||
magic_ = wrand(0xffff) + 1;
|
||||
}
|
||||
|
||||
inline void Update()
|
||||
{
|
||||
++magic_;
|
||||
|
||||
if (handle_ == 0) ++magic_;
|
||||
}
|
||||
|
||||
inline bool IsNull(void) const
|
||||
{
|
||||
return (!handle_);
|
||||
}
|
||||
inline unsigned int GetIndex(void) const
|
||||
{
|
||||
return (index_);
|
||||
}
|
||||
inline int64_t GetHandle(void) const
|
||||
{
|
||||
return (handle_);
|
||||
}
|
||||
inline static unsigned GetMaxIndex()
|
||||
{
|
||||
return 0xffffffff ;
|
||||
}
|
||||
inline operator int64_t (void) const
|
||||
{
|
||||
return (handle_);
|
||||
}
|
||||
inline Handle64& operator = (const int64_t v)
|
||||
{
|
||||
handle_ = v;
|
||||
return *this;
|
||||
}
|
||||
inline Handle64& operator = (const Handle64 v)
|
||||
{
|
||||
handle_ = v.handle_;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DATA, typename HDL, int ONE_TIME_COUNT = 1024>
|
||||
class HandleMgr :
|
||||
public AllocatorCounterItem
|
||||
{
|
||||
public:
|
||||
|
||||
typedef AllocatorCounterItem Inherited;
|
||||
struct tagHandle
|
||||
{
|
||||
HDL handle_;
|
||||
bool using_flag_;
|
||||
};
|
||||
|
||||
private:
|
||||
const static int BUFF_SIZE = sizeof(DATA) + sizeof(tagHandle);
|
||||
struct DataBlock
|
||||
{
|
||||
DataBlock* prev_;
|
||||
}* data_block_;
|
||||
public:
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
DATA* AllocHandle(HDL& handle)
|
||||
#else
|
||||
#define AllocHandle(handle) _AllocHandle(handle,__FILE__, __LINE__)
|
||||
#define Free(ptr) _Free(ptr, __FILE__, __LINE__)
|
||||
DATA* _AllocHandle(HDL& handle, const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
void* result = NULL;
|
||||
int count = free_list_.count();
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
count = all_list_.size() <= 0 ? ONE_TIME_COUNT : all_list_.size() * 2; //每次double
|
||||
|
||||
if (unsigned(all_list_.size() + count) > HDL::GetMaxIndex())
|
||||
{
|
||||
count = HDL::GetMaxIndex() - all_list_.size();
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
size_t allocsize = sizeof(DataBlock) + BUFF_SIZE * count;
|
||||
#else
|
||||
size_t allocsize = sizeof(DataBlock) + (BUFF_SIZE + sizeof(AllocBuffHead)) * count;
|
||||
#endif
|
||||
DataBlock* block_ptr = (DataBlock*)malloc(allocsize);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
alloc_total_ += allocsize;
|
||||
#endif
|
||||
//将对象指针全部添加到空闲列表中
|
||||
result = (void*)(block_ptr + 1);
|
||||
|
||||
int max_size = all_list_.size() + count;
|
||||
|
||||
if (free_list_.max_size() < max_size)
|
||||
free_list_.reserve(max_size);
|
||||
|
||||
int index = all_list_.size();
|
||||
void** list = free_list_;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
tagHandle* hdl_ptr = NULL;
|
||||
list[i] = result;
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)result;
|
||||
hdr->using_flag_ = false;
|
||||
hdr->buff_size_ = BUFF_SIZE;
|
||||
hdl_ptr = (tagHandle*)((char*)result + sizeof(AllocBuffHead));
|
||||
result = (void*)((char*)result + BUFF_SIZE + sizeof(AllocBuffHead));
|
||||
#else
|
||||
hdl_ptr = (tagHandle*)result;
|
||||
result = (void*)((char*)result + BUFF_SIZE);
|
||||
#endif
|
||||
hdl_ptr->handle_ = 0;
|
||||
hdl_ptr->handle_.Init(index);
|
||||
hdl_ptr->using_flag_ = false;
|
||||
index++;
|
||||
}
|
||||
|
||||
all_list_.addArray(free_list_, count); //已经分配的记录下
|
||||
//标记上内存块的上一个内存块
|
||||
block_ptr->prev_ = data_block_;
|
||||
data_block_ = block_ptr;
|
||||
}
|
||||
|
||||
//返回列表中的最后一个对象
|
||||
count--;
|
||||
result = free_list_[count];
|
||||
free_list_.trunc(count);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
used_count_ += BUFF_SIZE;
|
||||
#endif
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)result;
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_ == false);
|
||||
#endif
|
||||
|
||||
hdr->using_flag_ = true;
|
||||
hdr->al_.fn_ = file_name;
|
||||
hdr->al_.line_ = line;
|
||||
result = hdr + 1;
|
||||
#endif
|
||||
tagHandle* hdl_ptr = (tagHandle*)result;
|
||||
hdl_ptr->handle_.Update();//index不变,改magicnum
|
||||
result = (void*)((char*)result + sizeof(tagHandle));
|
||||
DATA* pd = (DATA*)result;
|
||||
new(pd)DATA(); //构造函数
|
||||
handle = hdl_ptr->handle_;
|
||||
hdl_ptr->using_flag_ = true;
|
||||
return pd;
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void Free(DATA* ptr)
|
||||
#else
|
||||
void _Free(DATA* ptr, const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
|
||||
tagHandle* hdl_ptr = (tagHandle*)ptr;
|
||||
hdl_ptr--;
|
||||
|
||||
//检查是否合法
|
||||
if (GetPtr(hdl_ptr->handle_) == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
SavePtr(hdl_ptr);
|
||||
#else
|
||||
SavePtr(hdl_ptr, file_name, line);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void Free(HDL handle)
|
||||
#else
|
||||
void _Free(HDL handle, const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
tagHandle* hdl_ptr = (tagHandle*)GetPtr(handle);
|
||||
|
||||
if (hdl_ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hdl_ptr--;
|
||||
#ifndef _MEMORY_TRACE_
|
||||
SavePtr(hdl_ptr);
|
||||
#else
|
||||
SavePtr(hdl_ptr, file_name, line);
|
||||
#endif
|
||||
}
|
||||
|
||||
//根据handle获取指针
|
||||
DATA* GetPtr(HDL handle)
|
||||
{
|
||||
//验证下这个指针是不是这里分配出去的
|
||||
int index = handle.GetIndex();
|
||||
|
||||
if (index < 0 || index >= all_list_.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* save_ptr = all_list_[index];
|
||||
#ifdef _MEMORY_TRACE_
|
||||
tagHandle* hdl_ptr = (tagHandle*)((char*)save_ptr + sizeof(AllocBuffHead));
|
||||
#else
|
||||
tagHandle* hdl_ptr = (tagHandle*)save_ptr;
|
||||
#endif
|
||||
HDL& h = hdl_ptr->handle_;
|
||||
|
||||
if (h.index_ != handle.index_ || h.magic_ != handle.magic_ || !hdl_ptr->using_flag_) //handle根本是不合法的
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (DATA*)((char*)hdl_ptr + sizeof(tagHandle));
|
||||
}
|
||||
|
||||
bool ReNew(HDL& handle)
|
||||
{
|
||||
// 检查有效性
|
||||
if (!GetPtr(handle)) return false;
|
||||
|
||||
handle.Update();
|
||||
int index = handle.GetIndex();
|
||||
void* save_ptr = all_list_[index];
|
||||
#ifdef _MEMORY_TRACE_
|
||||
tagHandle* hdl_ptr = (tagHandle*)((char*)save_ptr + sizeof(AllocBuffHead));
|
||||
#else
|
||||
tagHandle* hdl_ptr = (tagHandle*)save_ptr;
|
||||
#endif
|
||||
hdl_ptr->handle_ = handle; // 更新成新的handle
|
||||
return true;
|
||||
}
|
||||
|
||||
HandleMgr(const char* namestr)
|
||||
: Inherited(namestr)
|
||||
{
|
||||
data_block_ = NULL;
|
||||
}
|
||||
~HandleMgr()
|
||||
{
|
||||
#ifdef _MEMORY_TRACE_
|
||||
|
||||
for (int i = 0; i < all_list_.size(); i++)
|
||||
{
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)(all_list_[i]);
|
||||
|
||||
if (hdr->using_flag_)
|
||||
{
|
||||
char err[1024];
|
||||
SNPRINTFA(err, sizeof(err) - 1, " %s check memory leaks(size:%d),alloc:%s(%d)\n",
|
||||
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_);
|
||||
OutputWatchFile(err, "err.log");
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_ == false);//内存泄露了
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
DataBlock* block_ptr, *prev;
|
||||
block_ptr = data_block_;
|
||||
int block_count = 0;
|
||||
|
||||
while (block_ptr)
|
||||
{
|
||||
prev = block_ptr->prev_;
|
||||
free(block_ptr);
|
||||
block_ptr = prev;
|
||||
block_count++;
|
||||
}
|
||||
|
||||
data_block_ = NULL;
|
||||
#ifdef _MEMORY_TRACE_
|
||||
size_t free_size = free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock);
|
||||
if (free_size != alloc_total_)
|
||||
{
|
||||
char err[1024];
|
||||
SNPRINTFA(err, sizeof(err) - 1, "%s:%s:%d memory error,free size:%lld, alloc_size:%lld\n",
|
||||
__FUNCTION__, __FILE__, __LINE__, (long long int)free_size, (long long int)alloc_total_);
|
||||
OutputWatchFile(err, "err.log");
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
assert(free_size == alloc_total_); //简单的检查是否内存泄露
|
||||
#endif
|
||||
|
||||
#else
|
||||
assert(free_list_.count()*BUFF_SIZE + block_count * sizeof(DataBlock) == alloc_total_); //简单的检查是否内存泄露
|
||||
#endif
|
||||
}
|
||||
|
||||
//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:
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void SavePtr(tagHandle* hdl_ptr)
|
||||
#else
|
||||
void SavePtr(tagHandle* hdl_ptr, const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
//改掉magicnum
|
||||
hdl_ptr->using_flag_ = false;
|
||||
hdl_ptr->handle_.Update();
|
||||
|
||||
void* save_ptr = (void*) hdl_ptr;
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)save_ptr;
|
||||
hdr--;
|
||||
|
||||
if (!hdr->using_flag_)
|
||||
{
|
||||
printf(" %sFree the buff that had be release before(size:%d),alloc:%s(%d),free:%s(%d)\n",
|
||||
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_,
|
||||
hdr->fl_.fn_, hdr->fl_.line_);
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_);//检查有没有重复释放
|
||||
#endif
|
||||
|
||||
hdr->using_flag_ = false;
|
||||
hdr->fl_.fn_ = file_name;
|
||||
hdr->fl_.line_ = line;
|
||||
save_ptr = hdr;
|
||||
#endif
|
||||
DATA* data_ptr = (DATA*)(++hdl_ptr);
|
||||
data_ptr->~DATA();
|
||||
free_list_.add(save_ptr);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
used_count_ -= BUFF_SIZE;
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
container::Vector<void*> free_list_;
|
||||
container::Vector<void*> all_list_;//所有分配的内存都会在这里记录
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
172
Gateway/srvlib/include/memory/memory_container.hpp
Normal file
172
Gateway/srvlib/include/memory/memory_container.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#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_
|
||||
245
Gateway/srvlib/include/memory/memory_counter.hpp
Normal file
245
Gateway/srvlib/include/memory/memory_counter.hpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#ifndef _MEMORY_COUNTER_H_
|
||||
#define _MEMORY_COUNTER_H_
|
||||
|
||||
/************************************************************************
|
||||
* 内存分配统计
|
||||
* 每个用于内存分配的类最好都继承这个,并实现接口,好方便内存使用量的统计
|
||||
* 可通过宏定义_MEMORY_TRACE_ 开关
|
||||
***********************************************************************/
|
||||
#include "os_def.h"
|
||||
#include "share_util.h"
|
||||
#include <vector>
|
||||
#ifdef _MEMORY_TRACE_
|
||||
|
||||
template <typename T, int ONE_TIME_NUM = 16>
|
||||
class MemoryItemList
|
||||
{
|
||||
protected:
|
||||
T* data_ptr_;
|
||||
int max_size_;
|
||||
int count_;
|
||||
public:
|
||||
MemoryItemList()
|
||||
{
|
||||
data_ptr_ = NULL;
|
||||
max_size_ = 0;
|
||||
count_ = 0;
|
||||
}
|
||||
|
||||
virtual ~MemoryItemList()
|
||||
{
|
||||
empty();
|
||||
}
|
||||
|
||||
inline int count() const
|
||||
{
|
||||
return count_;
|
||||
}
|
||||
|
||||
int add(const T& data)
|
||||
{
|
||||
if (count_ >= max_size_)
|
||||
reserve((max_size_ > 0) ? max_size_ * 2 : ONE_TIME_NUM);
|
||||
|
||||
memcpy(data_ptr_ + count_, &data, sizeof(data));
|
||||
count_++;
|
||||
return count_ - 1;
|
||||
}
|
||||
|
||||
void remove(const int index)
|
||||
{
|
||||
assert(index > -1 && index < count_);
|
||||
remove(index, 1);
|
||||
}
|
||||
void remove(const int index, const int count)
|
||||
{
|
||||
assert(index + count <= count_);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
memmove(data_ptr_ + index, data_ptr_ + index + count, sizeof(data_ptr_[0]) * (count_ - index - count));
|
||||
count_ -= count;
|
||||
}
|
||||
}
|
||||
virtual void empty()
|
||||
{
|
||||
clear();
|
||||
max_size_ = 0;
|
||||
|
||||
if (data_ptr_)
|
||||
{
|
||||
free(data_ptr_);
|
||||
data_ptr_ = NULL;
|
||||
}
|
||||
}
|
||||
inline void clear()
|
||||
{
|
||||
count_ = 0;
|
||||
}
|
||||
virtual void reserve(int count)
|
||||
{
|
||||
if (count > count_ && count != max_size_)
|
||||
{
|
||||
max_size_ = count;
|
||||
data_ptr_ = (T*)realloc(data_ptr_, sizeof(T) * count);
|
||||
}
|
||||
}
|
||||
inline operator T* () const
|
||||
{
|
||||
return data_ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
class MemoryCounter;
|
||||
class AllocatorCounterItem
|
||||
{
|
||||
friend class MemoryCounter;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_NAME_LENGTH = 32, // 最大描述字符串长度
|
||||
};
|
||||
|
||||
AllocatorCounterItem(const char* namestr);
|
||||
|
||||
|
||||
virtual ~AllocatorCounterItem();
|
||||
|
||||
|
||||
const char* GetName()
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
virtual int Log(char* buf, int num)
|
||||
{
|
||||
const char* fmt = "%s, alloc total:%llu, used:%llu %s";
|
||||
const char* tip = GetTip(alloc_total_, used_count_);
|
||||
return SNPRINTFA(buf, num, fmt, name_, alloc_total_, used_count_, tip);
|
||||
}
|
||||
|
||||
size_t GetAllocCount()
|
||||
{
|
||||
return alloc_total_;
|
||||
}
|
||||
|
||||
const char* GetTip(size_t s1, size_t s2 = 0)
|
||||
{
|
||||
const char* tip = "";
|
||||
|
||||
if (s1 > largeCount || s2 > largeCount)
|
||||
{
|
||||
tip = "*****";
|
||||
}
|
||||
else if (s1 > midCount || s2 > midCount)
|
||||
{
|
||||
tip = "**";
|
||||
}
|
||||
|
||||
return tip;
|
||||
}
|
||||
|
||||
public:
|
||||
static const size_t largeCount = 100 * 1024 * 1024;
|
||||
static const size_t midCount = 10 * 1024 * 1024;
|
||||
protected:
|
||||
size_t alloc_total_; //分配的总数
|
||||
size_t free_count_; //空闲
|
||||
size_t used_count_; //正在使用的内存量
|
||||
char name_[MAX_NAME_LENGTH]; //
|
||||
};
|
||||
|
||||
class SimpleAllocCounter : public AllocatorCounterItem
|
||||
{
|
||||
static const int MAX_COUNTER = 8;
|
||||
public:
|
||||
SimpleAllocCounter(const char* name) : AllocatorCounterItem(name)
|
||||
{
|
||||
memset(counter_, 0, sizeof(counter_));
|
||||
}
|
||||
|
||||
size_t counter(size_t s, int idx)
|
||||
{
|
||||
assert(idx >= 0 && idx < MAX_COUNTER);
|
||||
counter_[idx] += s;
|
||||
alloc_total_ += s;
|
||||
return counter_[idx];
|
||||
}
|
||||
|
||||
virtual int Log(char* buf, int num)
|
||||
{
|
||||
const char* fmt = "%d, total:%llu %s\r\n";
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < MAX_COUNTER; i++)
|
||||
{
|
||||
size_t c = counter_[i];
|
||||
if (c <= 0) continue;
|
||||
|
||||
const char* tip = GetTip(c);
|
||||
|
||||
ret += SNPRINTFA(buf + ret, num - ret, fmt, i, c, tip);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
size_t counter_[MAX_COUNTER];
|
||||
};
|
||||
|
||||
class MemoryCounter
|
||||
{
|
||||
public:
|
||||
MemoryCounter();
|
||||
|
||||
static MemoryCounter& getSingleton()
|
||||
{
|
||||
static MemoryCounter mgr;
|
||||
return mgr;
|
||||
}
|
||||
|
||||
~MemoryCounter();
|
||||
|
||||
void clear()
|
||||
{
|
||||
allocator_list.clear();
|
||||
allocator_list.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Comments:添加一个统计项
|
||||
* @Return void:
|
||||
*/
|
||||
void regist(AllocatorCounterItem* item);
|
||||
|
||||
/*
|
||||
* Comments: 移除一个统计项
|
||||
* Param CSingleObjectAllocatorStat * stat:
|
||||
* @Return void:
|
||||
*/
|
||||
void unregist(AllocatorCounterItem* item);
|
||||
|
||||
/*
|
||||
* Comments: 统计信息到日志
|
||||
* @Return void:
|
||||
*/
|
||||
void logToFile();
|
||||
|
||||
private:
|
||||
MemoryItemList<AllocatorCounterItem*, 2048> allocator_list;
|
||||
};
|
||||
|
||||
#else //ifdef _MEMORY_TRACE_
|
||||
|
||||
class AllocatorCounterItem
|
||||
{
|
||||
public:
|
||||
AllocatorCounterItem(const char* namestr)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#endif //ifdef _MEMORY_TRACE_
|
||||
|
||||
#endif //end _ONCE_ALLOCATOR_H_
|
||||
213
Gateway/srvlib/include/memory/mempool.hpp
Normal file
213
Gateway/srvlib/include/memory/mempool.hpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#ifndef _MEMPOOL_H_
|
||||
#define _MEMPOOL_H_
|
||||
|
||||
/************************************************************************
|
||||
* 内存分配器,只分配固定大小的内存,适用于频繁创建实例的类,结构体之类
|
||||
************************************************************************/
|
||||
#include "os_def.h"
|
||||
#include "container/vector.h"
|
||||
#include "memory_counter.hpp"
|
||||
#include "allocdef.h"
|
||||
|
||||
template <int BUFF_SIZE, int ONE_TIME_COUNT = 1024>
|
||||
class MemPool :
|
||||
public AllocatorCounterItem
|
||||
{
|
||||
public:
|
||||
|
||||
typedef AllocatorCounterItem Inherited;
|
||||
|
||||
private:
|
||||
struct DataBlock
|
||||
{
|
||||
DataBlock* prev_;
|
||||
}* data_block_;
|
||||
public:
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void* Alloc()
|
||||
#else
|
||||
#define Alloc() _Alloc(__FILE__, __LINE__)
|
||||
#define Free(ptr) _Free(ptr, __FILE__, __LINE__)
|
||||
void* _Alloc(const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
void* result;
|
||||
int count = free_list_.count();
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
count = all_size_ > 0 ? all_size_ * 2 : ONE_TIME_COUNT; // 每次double
|
||||
all_size_ += count;
|
||||
#ifndef _MEMORY_TRACE_
|
||||
size_t allocsize = sizeof(DataBlock) + BUFF_SIZE * count;
|
||||
#else
|
||||
size_t allocsize = sizeof(DataBlock) + (BUFF_SIZE + sizeof(AllocBuffHead)) * count;
|
||||
#endif
|
||||
DataBlock* block_ptr = (DataBlock*)malloc(allocsize);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
alloc_total_ += allocsize;
|
||||
#endif
|
||||
//将对象指针全部添加到空闲列表中
|
||||
result = (void*)(block_ptr + 1);
|
||||
|
||||
if (free_list_.max_size() < all_size_)
|
||||
free_list_.reserve(all_size_);
|
||||
|
||||
void** list = free_list_;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
list[i] = result;
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)result;
|
||||
hdr->using_flag_ = false;
|
||||
hdr->buff_size_ = BUFF_SIZE;
|
||||
result = (void*)((char*)result + BUFF_SIZE + sizeof(AllocBuffHead));
|
||||
#else
|
||||
result = (void*)((char*)result + BUFF_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
all_list_.addArray(free_list_, count);//已经分配的记录下
|
||||
#endif
|
||||
//标记上内存块的上一个内存块
|
||||
block_ptr->prev_ = data_block_;
|
||||
data_block_ = block_ptr;
|
||||
}
|
||||
|
||||
//返回列表中的最后一个对象
|
||||
count--;
|
||||
result = free_list_[count];
|
||||
free_list_.trunc(count);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
used_count_ += BUFF_SIZE;
|
||||
#endif
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)result;
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_ == false); // 如果触发这个assert,这个是有严重的bug,这里先规避
|
||||
#endif
|
||||
hdr->using_flag_ = true;
|
||||
hdr->al_.fn_ = file_name;
|
||||
hdr->al_.line_ = line;
|
||||
result = hdr + 1;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void Free(void* ptr)
|
||||
#else
|
||||
void _Free(void* ptr, const char* file_name, int line)
|
||||
#endif
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)ptr;
|
||||
hdr--;
|
||||
|
||||
if (!hdr->using_flag_)
|
||||
{
|
||||
char err[1024];
|
||||
SNPRINTFA(err, sizeof(err) - 1, " %s Free the buff that had be release before(size:%d),alloc:%s(%d),free:%s(%d),now:%s(%d)\n",
|
||||
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_,
|
||||
hdr->fl_.fn_, hdr->fl_.line_, file_name, line);
|
||||
OutputWatchFile(err, "err.log");
|
||||
#ifdef _MSC_VER
|
||||
// 这个是有严重的bug,这里先规避,直接return
|
||||
assert(false);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_);//检查有没有重复释放
|
||||
#endif
|
||||
hdr->using_flag_ = false;
|
||||
hdr->fl_.fn_ = file_name;
|
||||
hdr->fl_.line_ = line;
|
||||
ptr = hdr;
|
||||
#endif
|
||||
free_list_.add(ptr);
|
||||
#ifdef _MEMORY_TRACE_
|
||||
used_count_ -= BUFF_SIZE;
|
||||
#endif
|
||||
}
|
||||
MemPool(const char* namestr)
|
||||
: Inherited(namestr)
|
||||
{
|
||||
data_block_ = NULL;
|
||||
all_size_ = 0;
|
||||
}
|
||||
|
||||
~MemPool()
|
||||
{
|
||||
#ifdef _MEMORY_TRACE_
|
||||
|
||||
for (int i = 0; i < all_list_.size(); i++)
|
||||
{
|
||||
AllocBuffHead* hdr = (AllocBuffHead*)(all_list_[i]);
|
||||
|
||||
if (hdr->using_flag_)
|
||||
{
|
||||
char err[1024];
|
||||
SNPRINTFA(err, sizeof(err) - 1, " %scheck memory leaks(size:%d),alloc:%s(%d)\n",
|
||||
__FUNCTION__, (int)hdr->buff_size_, hdr->al_.fn_, hdr->al_.line_);
|
||||
OutputWatchFile(err, "err.log");
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
assert(hdr->using_flag_ == false);//内存泄露了
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
DataBlock* block_ptr, *prev;
|
||||
block_ptr = data_block_;
|
||||
int block_count = 0;
|
||||
|
||||
while (block_ptr)
|
||||
{
|
||||
prev = block_ptr->prev_;
|
||||
free(block_ptr);
|
||||
block_ptr = prev;
|
||||
block_count++;
|
||||
}
|
||||
|
||||
data_block_ = NULL;
|
||||
#ifdef _MEMORY_TRACE_
|
||||
|
||||
size_t free_size = free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock);
|
||||
if (free_size != alloc_total_)
|
||||
{
|
||||
char err[1024];
|
||||
SNPRINTFA(err, sizeof(err) - 1, "%s:%s:%d memory error,free size:%lld, alloc_size:%lld\n",
|
||||
__FUNCTION__, __FILE__, __LINE__, (long long int)free_size, (long long int)alloc_total_);
|
||||
OutputWatchFile(err, "err.log");
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
assert(free_list_.count() * (BUFF_SIZE + sizeof(AllocBuffHead)) + block_count * sizeof(DataBlock) == alloc_total_); //简单的检查是否内存泄露
|
||||
#endif
|
||||
|
||||
#else
|
||||
//assert(free_list_.count()*BUFF_SIZE+block_count*sizeof(DataBlock) == alloc_total_);//简单的检查是否内存泄露
|
||||
#endif
|
||||
}
|
||||
|
||||
//public:
|
||||
//#ifdef _MEMORY_TRACE_
|
||||
// virtual int Log(char* buf, int num){ return sprintf(buf,"alloc total:%d,used:%d",alloc_total_,used_count); }
|
||||
//#endif
|
||||
|
||||
protected:
|
||||
container::Vector<void*> free_list_;
|
||||
int all_size_;
|
||||
|
||||
#ifdef _MEMORY_TRACE_
|
||||
container::Vector<void*> all_list_;//所有分配的内存都会在这里记录
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //end _MEMPOOL_H_
|
||||
55
Gateway/srvlib/include/memory/objpool.hpp
Normal file
55
Gateway/srvlib/include/memory/objpool.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef _OJBPOOL_H_
|
||||
#define _OJBPOOL_H_
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 内存分配器,只分配固定大小的类和结构体之类,
|
||||
* 和mempool的区别是会自动执行构造函数和析构函数
|
||||
************************************************************************/
|
||||
#include "os_def.h"
|
||||
#include "mempool.hpp"
|
||||
|
||||
template <typename T, int ONE_TIME_COUNT = 1024>
|
||||
|
||||
class ObjPool :
|
||||
public MemPool<sizeof(T), ONE_TIME_COUNT>
|
||||
{
|
||||
typedef MemPool<sizeof(T), ONE_TIME_COUNT> Inherited;
|
||||
public:
|
||||
ObjPool(const char* namestr)
|
||||
:Inherited(namestr)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef _MEMORY_TRACE_
|
||||
T* Alloc()
|
||||
{
|
||||
T* result = (T*)Inherited::Alloc();
|
||||
#else
|
||||
T* _Alloc(const char* fn, int line)
|
||||
{
|
||||
T* result = (T*)Inherited::_Alloc(fn, line);
|
||||
#endif
|
||||
new(result)T();
|
||||
return result;
|
||||
}
|
||||
#ifndef _MEMORY_TRACE_
|
||||
void Free(T* ptr)
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
ptr->~T();
|
||||
Inherited::Free(ptr);
|
||||
}
|
||||
#else
|
||||
void _Free(T* ptr, const char* fn, int line)
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
ptr->~T();
|
||||
Inherited::_Free(ptr, fn, line);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user