STL空间配置器之内存池技术
来源:互联网 发布:windows xp ping不通 编辑:程序博客网 时间:2024/05/29 08:09
注释的STL代码,算是为将来复习做个小笔记吧
#if 0#include<new>#define __THROW_BAD_ALLOC throw std::bad_alloc()#elif !defined(__THROW_BAD_ALLOC)#include<iostream>#define __THROW_BAD_ALLOC std::cerr<<"out of memory"<<std::endl; exit(1)#endif/*一级空间配置器*/template<int inst>class __malloc_alloc_template{private: /*下面两个函数都是内存不足时调用的*/ static void *oom_malloc(size_t n) { void(*my_malloc_handler)() = NULL; void *result = NULL; for (;;) { my_malloc_handler = __malloc_alloc_oom_handler; if (NULL == my_malloc_handler) { __THROW_BAD_ALLOC; } (*my_malloc_handler)(); result = malloc(n); if (NULL != result) return result; } } static void *oom_realloc(void *p, size_t n) { void(*my_malloc_handler)() = NULL; void *result = NULL; for (;;) { my_malloc_handler = __malloc_alloc_oom_handler; if (NULL == my_malloc_handler) { __THROW_BAD_ALLOC; } (*my_malloc_handler)(); result = realloc(p, n); if (NULL != result) return result; } } /*这个函数指针可以指向一个可以释放内存的函数,被上面两个函数判断如果有释放内存的函数就调用这个函数*/ static void(*__malloc_alloc_oom_handler)();public: static void *allocate(size_t n) { void * result = malloc(n); if (result == NULL) { result = oom_malloc(n); } return result; } static void deallocate(void *p, size_t/* n*/) { free(p); } static void *reallocate(void *p, size_t /*old_sz*/, size_t new_sz) { void *result = realloc(p, new_sz); if (NULL == result) { result = oom_realloc(p, new_sz); } return result; } static void(*set_malloc_handler(void(*f)()))() { void(*old)() = __malloc_alloc_oom_handler; __malloc_alloc_oom_handler = f; return old; }};typedef __malloc_alloc_template<0> malloc_alloc;#if 0//如果觉得没必要释放内存就把__malloc_alloc_oom_handler = NULLtemplate<int inst>void(*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = NULL;#else//如果觉得内存池很有可能申请不到内存char *preMem = new char[1024 * 1024 * 10];//可以先new出10M内存出来void delPreMem(){ delete preMem;//释放最开始申请的内存}template<int inst>void(*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = delPreMem;#endif/*二级空间配置器*/enum { __ALIGN = 8 }; //每个chunk之间的间隔 0 8 16 24enum { __MAX_BYTES = 128 }; //最大的chunkenum { __NFREELISTS = __MAX_BYTES / __ALIGN }; //list里面有几种chunktemplate<bool threads, int inst>class __default_malloc_template{private: union obj { union obj * free_list_link; //下一个相同chunk大小的地址 char client_data[1]; }; static obj * volatile free_list[__NFREELISTS];//自由链表,一共16个元素 /*上调bytes至8的倍数*/ static size_t ROUND_UP(size_t bytes) { return (bytes + __ALIGN - 1) & ~(__ALIGN - 1);//和 (bytes + 7) / 8 * 8;原理一样,先向右移动3位再向左移动3位 和 与0x11111000的效果一样 } /*找到bytes在free_list中的位置*/ static size_t FREELIST_INDEX(size_t bytes) { //return (bytes + __ALIGN - 1) / __ALIGN - 1;//STL上面是这样写的不过下面这样做更好 return ((bytes + __ALIGN - 1) >> 3) - 1; } static char * start_free;//内存池起始地址 static char * end_free;//内存池末尾地址 static size_t heap_size;//已经开辟的堆大小 /* 专门给free list提供内存的"内存池" 分配一大块空间(size * nobjs) size是用户现在需要的大小(但是我们不能用户需要多少给多少啊,给多一点放在内存池中管理) 但是如果当前内存池中的空闲内存没有那么大,nobjs能取多少就取多少(这样就能不需要malloc申请内存了啊) */ static char *chunk_alloc(size_t size, int &nobjs) { char * result = NULL; size_t total_bytes = size * nobjs; size_t bytes_left = end_free - start_free;/*当前池子还剩多少内存*/ if (bytes_left >= total_bytes)/*如果有那么大最好*/ { result = start_free; start_free += total_bytes; return result; } else if (bytes_left >= size) /*没有那么大我就退而求其次,只要能申请到就好*/ { nobjs = bytes_left / size; total_bytes = size*nobjs; result = start_free; start_free += total_bytes; return result; } else/*最基本的内存都申请不到就需要malloc了*/ { /*每次申请都会参考当前heap中的内存大小,需要的越多分配的越多*/ size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4); /*当前如果还剩的有内存就给一个合适的free list因为每个free都是8的倍数,所以一定有合适的free list*/ if (bytes_left > 0) { obj * volatile * my_free_list = free_list + FREELIST_INDEX(bytes_left); ((obj*)start_free)->free_list_link = *my_free_list; *my_free_list = (obj*)start_free; } /*配置heap空间,补充内存池*/ start_free = (char*)malloc(bytes_to_get); if (NULL == start_free) { int i; obj * volatile * my_free_list,*p; /*malloc失败我们还可以在其他free list中找内存*/ for (i = size; i <= __MAX_BYTES; i += __ALIGN) { my_free_list = free_list + FREELIST_INDEX(i); p = *my_free_list; if (NULL != p) { /*如果某个free list中有内存就切一个chunk给当前free list*/ *my_free_list = p->free_list_link;//指向下一个chunk start_free = (char *)p; end_free = start_free + i; /*找到了一点内存,递归调用*/ return chunk_alloc(size, nobjs); } } /*如果free list都没有内存了,就调用一级配置器看out-of-memory机制能否尽点力释放点内存*/ start_free = (char*)malloc_alloc::allocate(bytes_to_get); } heap_size += bytes_to_get; end_free = start_free + bytes_to_get; return chunk_alloc(size, nobjs); } } /*free list中的chunk不够了调用这个填充函数*/ static void *refill(size_t n) // 16 { int nobjs = 20;//默认20个chunk char * chunk = chunk_alloc(n, nobjs); obj * result = NULL; obj * current_obj, *next_obj; int i; /*如果只分配了一个chunk那么直接返回*/ if (nobjs == 1) return chunk; /*分配了多个就需要把后面的chunk串起来*/ obj * volatile * my_free_list = free_list + FREELIST_INDEX(n); result = (obj*)chunk; *my_free_list = next_obj = (obj*)(chunk + n); for (i = 1;; ++i) { current_obj = next_obj; next_obj = (obj*)((char*)next_obj + n); if (i == nobjs - 1) { current_obj->free_list_link = NULL; break; } current_obj->free_list_link = next_obj; } return result; }public: /*空间配置函数*/ static void *allocate(size_t n)// n // 20 { obj * volatile * my_free_list = NULL; obj * result = NULL; /*大于128调用一级配置器*/ if (n > (size_t)__MAX_BYTES) { return malloc_alloc::allocate(n); } /*寻址16个free list中最合适的一个*/ my_free_list = free_list + FREELIST_INDEX(n); result = *my_free_list; if (NULL == result) { /*当前free list没有chunk,填充这个free list*/ void *r = refill(ROUND_UP(n)); return r; } *my_free_list = result->free_list_link;//当前free list的第一个chunk将要分配出去,所以指向下一个chunk return result; } /*空间释放函数*/ static void deallocate(void *p, size_t n) { obj * volatile * my_free_list = NULL; obj * q = (obj*)p; /*大于128调用一级配置器释放(其实就是直接free掉)*/ if (n > (size_t)__MAX_BYTES) { malloc_alloc::deallocate(p, n); return; } /*找到对应的free list把当前归还的chunk进行头插法*/ my_free_list = free_list + FREELIST_INDEX(n); q->free_list_link = *my_free_list; *my_free_list = q; } /*调整内存大小*/ static void *reallocate(void *p, size_t old_sz, size_t new_sz) { void * result; size_t copy_sz; if (old_sz > (size_t)__MAX_BYTES && new_sz > (size_t)__MAX_BYTES) { return(malloc_alloc::reallocate(p, old_sz, new_sz)); } if (ROUND_UP(old_sz) == ROUNDP_UP(new_sz)) return(p); result = allocate(new_sz); copy_sz = new_sz > old_sz ? old_sz : new_sz; memcpy(result, p, copy_sz); deallocate(p, old_sz); return(result); }};template<bool threads, int inst>typename __default_malloc_template<threads, inst>::obj * volatile __default_malloc_template<threads, inst>::free_list[__NFREELISTS] = { NULL };template<bool threads, int inst>char * __default_malloc_template<threads, inst>::start_free = NULL;template<bool threads, int inst>char * __default_malloc_template<threads, inst>::end_free = NULL;template<bool threads, int inst>size_t __default_malloc_template<threads, inst>::heap_size = 0;/*配置器标准接口*/#ifdef __USE_MALLOC typedef __malloc_alloc_template<0> malloc_alloc; typedef malloc_alloc alloc;#else typedef __default_malloc_template<0, 0> alloc;//默认使用二级配置器#endiftemplate<class T, class Alloc>class simple_alloc{public: static T * allocate(size_t n) // new [] { return n == 0 ? NULL : (T*)Alloc::allocate(n * sizeof(T)); } static T * allocate() // new { return (T*)Alloc::allocate(sizeof(T)); } static void deallocate(void *p, size_t n)//delete[] { if (n == 0) return; Alloc::deallocate(p, n*sizeof(T)); } static void deallocate(void *p) //delete { Alloc::deallocate(p, sizeof(T)); }};
0 0
- STL空间配置器之内存池技术
- SGI STL源码之内存配置
- STL之内存处理
- STL之内存管理
- 经典数据结构之内存池技术
- 【STL】STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- 【STL】空间配置器
- STL空间配置器
- STL----空间配置器
- STL-空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL-空间配置器
- java基础——数据类型,变量,运算符,字符串,输入输出,数组,大数值
- 438. Find All Anagrams in a String
- OpenCV之Python学习笔记
- C/C++求职者必备的20道面试题
- 远程桌面连接树莓派
- STL空间配置器之内存池技术
- 大数据学习之HDP SANDBOX开始学习
- Android中Adapter的一种简介的设计
- linux下的创建子进程的方法
- building machine learning system with Python 学习笔记--从零开始机器学习(2)第一章
- 解答:为什么判断一个数是否为素数时只需开平方根就行了!
- tomcat自动部署代码脚本
- linux011-unstd.h头文件
- uboot移植第四天——代码分析(4)