Files
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

464 lines
9.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 _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