464 lines
9.4 KiB
C++
464 lines
9.4 KiB
C++
#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
|