设计上:
(1)内存分配器管理器(nMemoryAlloc):
内存分配器管理器含有针对不同内存大小的内存池数组。每个内存池对象含有空闲节点链表,管理分配和回收的节点对象内存。
(2)链表节点内存:
链表节点对象含有变长内存成员,适合分配各个长度的内存对象。但同一个内存池对象中的节点内存大小是一致的。
(3)内存分配原则:
1)内存分配器nMemoryAlloc对于内存大小在1~1024 * 1024 字节之间小对象使用内存池的管理,否则就使用系统默认的分配和删除接口,让系统管理内存。
2)内存分配器适用的是定长的类型。
(4)静态存储区使用:
内存池管理器中的内存池数组是静态的,对外提供静态接口。
(5)空间配置器:
空间配置器使用内存池管理器来管理器内存
内存池分配节点,没有内存就向系统申请,否则从空闲列表中获取。
内存池含空闲节点链表。
class MemPool2 { private: struct _Node { _Node():next(NULL) { } ~_Node() { } _Node* next; unsigned char data[0];//变长内存 }; _Node* mFreeNodeList; public: unsigned long _all_alloc_size;//总共分配内存大小计数 unsigned long _all_alloc_num;//分配节点计数 unsigned long _all_use_num;//使用节点计数 unsigned long _all_free_num;//空闲节点计数 public: MemPool2() : mFreeNodeList(NULL),_all_alloc_size(0),_all_alloc_num(0),_all_use_num(0),_all_free_num(0) { } void reset()//释放链表所有节点内存 { _Node* p = mFreeNodeList; while(p) { _all_free_num ++; _Node* _p = p; p = p->next; char *tmp = (char *)_p; free(tmp); } mFreeNodeList = NULL; } ~MemPool2(void) { _Node* p = mFreeNodeList; while(p) { _Node* _p = p; p = p->next; char *tmp = (char *)_p; free(tmp); } mFreeNodeList = NULL; } _Node* __allocData(int datasize)//实际分配节点(没有内存就向系统申请,否则从空闲列表中获取) { if(!mFreeNodeList) { _all_alloc_size += (sizeof(_Node) + datasize);//记录总分配大小 _all_alloc_num ++;//记录分配节点数 char *tmp = (char *)malloc(sizeof(_Node) + datasize); mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); } _all_use_num ++; _Node* p = mFreeNodeList; mFreeNodeList = mFreeNodeList->next; return p;//返回节点 } unsigned char* alloc0(int datasize)//分配节点(没有内存就向系统申请,否则从空闲列表中获取) { _Node* p = __allocData(datasize); return (unsigned char*)(p->data); } void freePtr(unsigned char* &p)//回收节点的内存回链表表头 { if (p) { _Node* pNod = (_Node*)(p - sizeof(_Node));//上一个链表节点(分配过的就会有) pNod->next = mFreeNodeList; mFreeNodeList = pNod; p = NULL; _all_use_num --; } } void freePtr(char* p)//回收节点的内存回链表表头(_Node + 实际内存) { if (p) { _Node* pNod = (_Node*)(p - sizeof(_Node)); pNod->next = mFreeNodeList; mFreeNodeList = pNod; _all_use_num --; } } }; 其中:在指定地址构造对象 template<class T> inline void constructInPlace(T *_Ptr) { // construct object at _Ptr with value _Val new ((void *)_Ptr) T(); }
class nMemoryAlloc { protected: nMemoryAlloc() { }; ~nMemoryAlloc() { }; public: //锁(单线程不使用) static zMutex alloc_lock[1024 * 1024 + 1024]; //内存池数组 //数据大小在1024 * 1024字节 以内的对象才可以使用内存池分配和回收,否则使用系统函数分配和删除 //使用哪个内存池是按字节大小(包含节点头)来获取需要使用的内存池 static MemPool2 alloc[1024 * 1024 + 1024]; public: static void* operator new( size_t Size , void *); static void* operator new( size_t Size , void *,const char* filename,int line ); static void* operator new( size_t Size); static void* operator new( size_t Size,const char* filename,int line ); static void operator delete( void* Ptr ); static void operator delete( void* Ptr ,const char* , int); static void* operator new[]( size_t Size , void *); static void* operator new[]( size_t Size , void *,const char* filename,int line); static void* operator new[]( size_t Size ); static void* operator new[]( size_t Size ,const char* filename,int line); static void operator delete[]( void* Ptr ); static void operator delete[]( void* Ptr ,const char* , int); public: static void *allocator(size_t Size); static void free(void* Ptr); };
数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除。
1)小对象分配使用内存分配器
2)大对象就直接分配
//释放一个内存对象 void* nMemoryAlloc::operator new( size_t Size ) { assert(Size != 0); Size += sizeof(_Node); Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐 //数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除 if(Size < 1024 * 1024)//小对象分配使用内存分配器 { zMutex_scope_lock lock(alloc_lock[Size]); void *tmp = alloc[Size].alloc0(Size); _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); mFreeNodeList->size = Size; return mFreeNodeList->data; } else//大对象就直接分配 { void *tmp = malloc( Size ); _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); mFreeNodeList->size = Size; return mFreeNodeList->data; } } //释放内存对象数组 void* nMemoryAlloc::operator new[]( size_t Size ) { assert(Size != 0); Size += sizeof(_Node); Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐 //数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除 if(Size < 1024 * 1024)//小对象分配使用内存分配器 { zMutex_scope_lock lock(alloc_lock[Size]); void *tmp= alloc[Size].alloc0(Size);//内存池分配(内存池的选择跟分配的大小是一致的) _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList);//placement new 构造对象 mFreeNodeList->size = Size; return mFreeNodeList->data; } else//大对象就直接分配 { void *tmp = malloc( Size ); _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); mFreeNodeList->size = Size; return mFreeNodeList->data; } } //回收对象 //数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除 void nMemoryAlloc::operator delete( void* Ptr ) { if (!Ptr) { return; } _Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node));//获取内存的节点头 if(pNod->size && pNod->size < 1024 * 1024)//数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除 { alloc[pNod->size].freePtr((char *)pNod); return; } else { ::free( pNod ); } } //删除对象数组 void nMemoryAlloc::operator delete[]( void* Ptr ) { if (!Ptr) { return; } _Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node)); if(pNod->size < 1024 * 1024 && pNod->size != 0) { alloc[pNod->size].freePtr((char *)pNod); return; } else { ::free( pNod ); } }
数据大小在1024 * 1024字节 以内的才可以使用内存池分配和回收,否则使用系统函数分配和删除。
1)小对象分配使用内存分配器
2)大对象就使用系统函数分配和删除
void *nMemoryAlloc::allocator(size_t Size) { Size += sizeof(_Node); Size = (Size + 0X3F) & (0XFFFFFFFF - 0X3F);//64字节对齐 if(Size < 1024 * 1024) { void *tmp= alloc[Size].alloc0(Size); _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); mFreeNodeList->size = Size; return mFreeNodeList->data; } else { void *tmp = malloc( Size ); _Node *mFreeNodeList = (_Node *)tmp; constructInPlace(mFreeNodeList); mFreeNodeList->size = Size; return mFreeNodeList->data; } } void nMemoryAlloc::free(void* Ptr) { if (!Ptr) { return; } _Node* pNod = (_Node*)((char *)Ptr - sizeof(_Node)); if(pNod->size && pNod->size < 1024 * 1024) { zMutex_scope_lock lock(alloc_lock[pNod->size]); alloc[pNod->size].freePtr((char *)pNod); return; } else { ::free( pNod ); } }
1)基本类型应用
使用对象分配器的对象
struct StateObject:public nMemoryAlloc//使用的类型
{
....
};
2)在空间配置器中的使用
自定义空间配置器,内存的分配和回收是使用内存池分配管理器。空间配置器是在容器内加入元素和删除元素和容器析构时会使用。
template <class _Ty> class nMemoryAllocator { public: typedef size_tsize_type; typedef _Ty *pointer; typedef _Ty & reference; typedef const _Ty *const_pointer; typedef const _Ty & const_reference; typedef _Ty value_type; typedef int difference_type; nMemoryAllocator() { // construct default allocator (do nothing) } //赋值函数重载 template<class _Other> nMemoryAllocator<_Ty>& operator = (const nMemoryAllocator<_Other>& alr) { // assign from a related allocator (do nothing) return (*this); } //拷贝构造函数重载 template<class _Other> nMemoryAllocator(const nMemoryAllocator<_Other>& alr) { // construct by copying (do nothing) } //重绑定类型到自定义的空间配置器 template<class _Other> struct rebind { // convert an allocator<_Ty> to an allocator <_Other> typedef nMemoryAllocator<_Other> other; }; //内存分配(参数分配对象个数) pointer allocate(size_type _Count)//分配原始的构造内存以保存T类型的n个对象 { if(_Count == 0) _Count = 1; return (pointer)nMemoryAlloc::allocator(sizeof(_Ty) * _Count);//从内存管理器获取内存 } //内存分配(参数分配对象个数) pointer allocate(size_type _Count,const void *) { if(_Count == 0) _Count = 1; return (pointer)nMemoryAlloc::allocator(sizeof(_Ty) * _Count);//从内存管理器获取内存 } //返回引用地址 pointer address(reference _Val) const { // return address of mutable _Val return (&_Val); } //返回引用地址 const_pointer address(const_reference _Val) const { // return address of nonmutable _Val return (&_Val); } //构造对象(成员) void construct(pointer _Ptr, const _Ty& _Val)//指针p所指向的内存中构造一个新对象 { ::new(static_cast<void*>(<span style="font-family: Arial, Helvetica, sans-serif;">_Ptr</span>)) <span style="font-family: Arial, Helvetica, sans-serif;">_Ty</span>(<span style="font-family: Arial, Helvetica, sans-serif;">_Val</span>);//std::_Construct(_Ptr,_Val); } //析构对象(回收到内存池管理器) void deallocate(pointer _Ptr, size_type size) //释放内存,在名为p的T*指针含的地址处保存T类型的n个对象 <pre code_snippet_id="439793" snippet_file_name="blog_20140731_5_33916" name="code" class="cpp"> { // deallocate object at _Ptr, ignore sizenMemoryAlloc::free(_Ptr);}//销毁对象void destroy(pointer _Ptr){ // destroy object at _Ptr_Ptr->~_Ty();;//析构对象 std::_Destroy(_Ptr);}//能够分配的大小(准确的估计需要重新计算)size_t max_size() const{ // estimate maximum array sizesize_t _Count = (size_t)(-1) / sizeof (_Ty);return (0 < _Count ? _Count : 1);}};//重载等号操作符template<class _Ty,class _Other>inline bool operator == (const nMemoryAllocator<_Ty>& alr1,const nMemoryAllocator<_Other>& alr2){ // assign from a related allocator (do nothing)return true;} //重载不等操作符template<class _Ty,class _Other>inline bool operator != (const nMemoryAllocator<_Ty>& alr1,const nMemoryAllocator<_Other>& alr2){ // assign from a related allocator (do nothing)return false;}
1)字符串string类型
typedef std::basic_string<char, std::char_traits<char>, nMemoryAllocator<char> > string;
typedef std::string string;
2)基类写流basic_ostream类型
template<typename T>
struct basic_ostream: public std::basic_ostream<T, nMemoryAllocator<T> >{};
typedef std::basic_ostream<char, zMemoryAllocator<char> > basic_ostream;
3)基类读流basic_istream类型
template<typename T>
struct basic_istream: public std::basic_istream<T, nMemoryAllocator<T> >{};
typedef std::basic_istream<char, zMemoryAllocator<char> > basic_istream;
4)vector类型
template<typename T>
struct vector: public std::vector<T ,nMemoryAllocator<T> >
{
vector(){}
vector(int size):std::vector<T ,nMemoryAllocator<T> >(size){}
vector(const Zebra::vector<T>& v):std::vector<T ,nMemoryAllocator<T> >(v){}
};
template<typename T>
struct list: public std::list<T ,nMemoryAllocator<T> >{};
容器使用
使用自定义空间配置器的对象列表
typedef Zebra::vector<StateObject *> stateVector; //使用的容器