C++SGI版本STL内存管理

来源:互联网 发布:淘宝企业开店要钱吗 编辑:程序博客网 时间:2024/05/16 14:35

首先声明:这是本人对于SGI内存池实现的基本流程的理解,希望大家能借鉴并纠正不对的地方



实现代码:

#pragma once#include <stdarg.h>#include <iostream>using namespace std;#define __DEBUG__static string GetFileName(const string& path){char ch='/';#ifdef _WIN32ch ='\\';#endifsize_t pos = path.rfind(ch);if(pos==string::npos)return path;elsereturn path.substr(pos+ 1);}//用于调试追溯的trace loginline static void __trace_debug(const char* function, const char* filename,int line,char* format, ...){#ifdef __DEBUG__//输出调用函数的信息fprintf(stdout,"【%s:%d】%s",GetFileName(filename).c_str() , line , function);//输出用户打的trace信息va_list args;va_start(args,format);vfprintf(stdout,format,args);va_end(args);#endif}#define __TRACE_DEBUG(...)  \__trace_debug(__FUNCTION__,__FILE__,__LINE__,__VA_ARGS__);typedef void(*HandlerFunc)();template <int inst>class __MallocAllocTemplate{private:static void *oomMalloc(size_t size){while (1){if (__malloc_alloc_oom_handler == 0){throw bad_alloc();}else{(*__malloc_alloc_oom_handler)();void* ret = malloc(size);if (ret)return ret;}}}//static void (* __malloc_alloc_oom_handler)();static HandlerFunc __malloc_alloc_oom_handler;public:static void* Allocate(size_t n){__TRACE_DEBUG("一级空间配置器分配内存:%d\n", n);void *result = malloc(n);if (0 == result)result = oomMalloc(n);return result;}static void Deallocate(void *p, size_t /* n */){free(p);}static HandlerFunc SetMallocHandler(HandlerFunc f)//static void (* set_malloc_handler(void (*f)()))(){void (* old)() = __malloc_alloc_oom_handler;__malloc_alloc_oom_handler = f;return(old);}};/*template <int inst>void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;*/template<int inst>void(*__MallocAllocTemplate<inst>::__malloc_alloc_oom_handler)() = 0;template <bool threads, int inst>class __DefaultAllocTemplate{enum {__ALIGN = 8};enum {__MAX_BYTES = 128};enum {__NFREELISTS = __MAX_BYTES/__ALIGN};union Obj {union Obj* _freeListLink;char client_data[1];    /* The client sees this.        */};static Obj* _freeList[__NFREELISTS]; // Chunk allocation state.static char* _startFree;// 内存池的开始static char* _endFree;// 内存池的结束static size_t _heapSize;// 已分配内存的大小<span style="color:#ff0000;">static  size_t FREELIST_INDEX(size_t bytes){return (((bytes) + __ALIGN-1)/__ALIGN - 1);}static size_t ROUND_UP(size_t bytes){return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));}    //个人觉得此处应有掌声</span>public:static char* ChunkAlloc(size_t n, size_t& nobjs){char* ret = NULL;size_t totalBytes = n * nobjs;size_t bytesLeft = _endFree - _startFree;if (bytesLeft >= totalBytes){__TRACE_DEBUG("内存池有足够nobjs:%d个对象的内存\n", nobjs);ret = _startFree;_startFree += totalBytes;return ret;}else if (bytesLeft >= n){nobjs = bytesLeft/n;__TRACE_DEBUG("只有nobjs:%d个对象的内存\n", nobjs);totalBytes = nobjs*n;ret = _startFree;_startFree += totalBytes;return ret;}else{// 计算向系统申请的字节数size_t bytesToGet = totalBytes*2 + ROUND_UP(_heapSize>>4);// 处理内存池剩余的字节数if(bytesLeft > 0){size_t index = FREELIST_INDEX(bytesLeft);((Obj*)_startFree)->_freeListLink = _freeList[index];_freeList[index] = (Obj*)_startFree;}__TRACE_DEBUG("找系统分配%d字节的内存\n", bytesToGet);_startFree = (char*)malloc(bytesToGet);if (_startFree == NULL){// 在更大的自由链表中去取for(size_t i = n; i <= __MAX_BYTES; i+=__ALIGN){size_t index =  FREELIST_INDEX(i);if (_freeList[index]){_startFree = (char*)_freeList[index];_freeList[index] = ((Obj*)_startFree)->_freeListLink;_endFree = _startFree+i;return ChunkAlloc(n, nobjs);}}// 山穷水尽--调用一级空间_endFree = 0;_startFree = (char*)__MallocAllocTemplate<0>::Allocate(bytesToGet);}_endFree = _startFree+bytesToGet;_heapSize += bytesToGet;return ChunkAlloc(n, nobjs);}}static void* Refill(size_t n){// 分配nobjs个对象的大小size_t nobjs = 20;char* chunk = ChunkAlloc(n, nobjs);if(nobjs == 1)return chunk;__TRACE_DEBUG("挂内存块到自由链表nobjs:%d\n", nobjs);// 挂内存块Obj* cur, *next;size_t index = FREELIST_INDEX(n);cur = (Obj*)(chunk + n);_freeList[index] = cur;for (size_t i = 1; i < nobjs-1; ++i){next = (Obj*)((char*)cur+n);cur->_freeListLink = next;cur = next;}cur->_freeListLink = NULL;return chunk;}static void * Allocate(size_t n){__TRACE_DEBUG("二级空间配置器分配内存:%d\n", n);if (n > __MAX_BYTES){return __MallocAllocTemplate<0>::Allocate(n);}size_t index = FREELIST_INDEX(n);if (_freeList[index] == 0){return Refill(ROUND_UP(n)); // ?}else{__TRACE_DEBUG("到自由链表中去取内存块:%d\n", index);Obj* first = _freeList[index];_freeList[index] = first->_freeListLink;return first;}}static void Deallocate(void* p , size_t n){if (n > __MAX_BYTES){__MallocAllocTemplate<0>::Deallocate(p, n);}size_t index = FREELIST_INDEX(n);Obj* obj = (Obj*)p;obj->_freeListLink = _freeList[index];_freeList[index] = obj;}};template<class T, class Alloc>class SimpleAlloc{public:static T* Allocate(size_t n){ return 0 == n? 0 : (T*) Alloc::Allocate(n * sizeof (T));}static T* Allocate(void){ return (T*) Alloc::Allocate(sizeof (T));}static void Deallocate(T *p, size_t n){ if (0 != n)Alloc::Deallocate(p, n * sizeof (T));}static void Deallocate(T *p){ Alloc::Deallocate(p, sizeof (T));}};template <bool threads, int inst>typename __DefaultAllocTemplate<threads, inst>::Obj*__DefaultAllocTemplate<threads, inst>::_freeList[__NFREELISTS] = {0};// Chunk allocation state.template <bool threads, int inst>char* __DefaultAllocTemplate<threads, inst>::_startFree = 0;template <bool threads, int inst>char* __DefaultAllocTemplate<threads, inst>::_endFree = 0;template <bool threads, int inst>size_t __DefaultAllocTemplate<threads, inst>::_heapSize = 0;#ifdef __USE_MALLOCtypedef __MallocAllocTemplate<0> Alloc;#elsetypedef __DefaultAllocTemplate<false, 0> Alloc;#endif // __USE_MALLOC


测试:

// 测试内存池的一级、二级配置器功能void Test1 (){// 测试调用一级配置器分配内存cout<<" 测试调用一级配置器分配内存 "<<endl ;char*p1 = SimpleAlloc< char, Alloc>::Allocate (129);SimpleAlloc<char , Alloc>:: Deallocate(p1 , 129);// 测试调用二级配置器分配内存cout<<" 测试调用二级配置器分配内存 "<<endl ;char*p2 = SimpleAlloc< char, Alloc>::Allocate (128);char*p3 = SimpleAlloc< char, Alloc>::Allocate (128);char*p4 = SimpleAlloc< char, Alloc>::Allocate (128);char*p5 = SimpleAlloc< char, Alloc>::Allocate (128);SimpleAlloc<char , Alloc>:: Deallocate(p2 , 128);SimpleAlloc<char , Alloc>:: Deallocate(p3 , 128);SimpleAlloc<char , Alloc>:: Deallocate(p4 , 128);SimpleAlloc<char , Alloc>:: Deallocate(p5 , 128);for (int i = 0; i < 21; ++i ){printf(" 测试第%d次分配 \n", i +1);char*p = SimpleAlloc< char, Alloc>::Allocate (128);}}


0 0
原创粉丝点击