STL空间配置器
来源:互联网 发布:mysql服务器 编辑:程序博客网 时间:2024/06/06 05:32
当用户申请的内存大于128时调用一级空间配置器。
小于或者等于128调用二级空间配置器。
一级空间配置器是malloc的封装,如果不能成功申请到空间,用户通过调用set_malloc_handler函数可以自己设定处理函数。
二级空间配置器类似哈希桶,将128的区块分为16个分别为8,16,24。。。128大小的区块,用free_list来保存.
用户每次申请小于128的内存,会提升的8的整数倍,释放后会加入到对应的区块中,下一次申请时在free_list中查找对应的区块,如果没有,再到内存池中获取。很大的提升了效率并且易于管理。
#include <iostream>using namespace std;//当用户申请内存大于128时使用一级空间配置器template <int inst>class malloc_Alloc_template { public: static void *allocate(size_t n) { void *result = malloc(n); if (n == 0) result = oom_malloc(n); //不满足要求进行处理 return result; } static void dellocate(void *p, size_t) { free(p); } static void *reallocate(void *p, size_t old_size, size_t new_size) { void *result = realloc(p, new_size); if (0 == result) result = oom_realloc(p, new_size); return result; } static void(*set_malloc_handler(void(*f)()))()//用户可以自己设定 //没有内存时重新分配的函数 { void(*old)() = alloc_oom_handler; alloc_oom_handler = f; return old; }private: static void(* alloc_oom_handler)();private: static void *oom_malloc(size_t n) { void *result; void(*f)(); for (;;) { f = alloc_oom_handler; if (NULL == f) { cerr << "out of merroy" << endl; exit(1); } (*f)(); result = malloc(n); if (result) return result; } } static void oom_realloc(void *p, size_t new_size) { void *result; void(*f)(); for (;;) { f = alloc_oom_handler; if (NULL == f) { cerr << "out of merroy" << endl; exit(1); } *f(); result = rellocc(p, old_size); if (result) return result; } }};template <int inst>void(*malloc_Alloc_template<inst>::alloc_oom_handler)() = NULL; //静态成员初始化typedef malloc_Alloc_template<0> malloc_Alloc;//二级空间配置器enum { ALIGN = 8 }; //小区块上界enum { MAX_BYTES = 128 }; //区块上限enum { FREELIST = MAX_BYTES / ALIGN }; //小区块个数template <int inst>class default_Alloc_template {public: static void *allocate(size_t n); static void *reallocate(void *p, size_t old_size, size_t new_size); static void deallocate(void *p, size_t n);private: //用于提升申请内存大小到小区块上界的倍数 static size_t ROUND_UP(size_t bytes) { return ((bytes + ALIGN - 1) & ~(ALIGN - 1)); } //下标 static size_t FREELIST_INDEX(size_t bytes) { return ((bytes + ALIGN - 1) / ALIGN - 1); } static void *refill(size_t n); static char* chunk_alloc(size_t size, int &nobjs);private: union obj{ union obj* free_list_link; char client_data[1]; };private: static obj* volatile free_list[FREELIST]; static char* start_free; //内存池起始位置 static char* end_free; //内存池结束位置 static size_t heap_size;};template <int inst>char *default_Alloc_template<inst>::start_free = 0;template <int inst>char *default_Alloc_template<inst>::end_free = 0;template <int inst>size_t default_Alloc_template<inst>::heap_size = 0;template <int inst>typename default_Alloc_template<inst>::obj* volatiledefault_Alloc_template<inst>::free_list[FREELIST] = {0};template <int inst>void* default_Alloc_template<inst>::allocate(size_t n){ obj* volatile *my_free_list; obj* result; // 大于128调用一级空间配置器 if (n > (size_t)MAX_BYTES) { return (malloc_Alloc::allocate(n)); } //判断应该使用my_free_list应该使用16个中的哪一个 my_free_list = free_list + FREELIST_INDEX(n); result = *my_free_list; //没有找到,说明没有所需要的free_list if (0 == result) { void *r = refill(ROUND_UP(n)); return r; } //有所需要的free_list,free_list指向下一个 *my_free_list = result->free_list_link; return result;}template <int inst>void default_Alloc_template<inst>::deallocate(void *p, size_t n){ obj *q = (obj *)p; obj * volatile *my_free_list; //大于128调用1级空间配置器的函数 if (n > (size_t)FREELIST) { malloc_Alloc::dellocate(p, n); return; } my_free_list = free_list + FREELIST_INDEX(n); q->free_list_link = *my_free_list; *my_free_list = q;}//freelist没有可用的区块时,调用refill填充新空间template <int inst>void* default_Alloc_template<inst>::refill(size_t n){ //默认取得20个区块 int nobjs = 20; //从内存池取得区块给free_list使用 char *chunk = chunk_alloc(n, nobjs); obj* volatile *my_free_list; obj* result; obj* cur_obj; obj* next_obj; int i; //只取得了一个,直接交给调用者 if (1 == nobjs) return chunk; my_free_list = free_list + FREELIST_INDEX(n); result = (obj*)chunk; *my_free_list = next_obj = (obj*)(chunk + n); //将剩余的区块交给free_list,各节点连接起来 for (i = 1;; ++i) { cur_obj = next_obj; next_obj = (obj*)((char*)next_obj + n); if (nobjs - 1 == i) { cur_obj->free_list_link = 0; break; } else { cur_obj->free_list_link = next_obj; } } return result;}//从内存池取得空间交给free_list使用template <int inst>char *default_Alloc_template<inst>::chunk_alloc(size_t size, int &nobjs){ char *result; 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 = nobjs*size; result = start_free; start_free += total_bytes; return result; } //剩余内存无法提供1个大小的区块 else { size_t bytes_toget = 2 * total_bytes + ROUND_UP(heap_size >> 4); 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_toget); if (0 == start_free) { //heap空间不足,malloc失败 int i; obj* volatile *my_free_list; obj* p; //从更大的区块尝试获取 for (i = size; i <= MAX_BYTES; i += ALIGN) { my_free_list = free_list + FREELIST_INDEX(i); p = *my_free_list; if (0 != p) { *my_free_list = p->free_list_link; start_free = (char*)p; end_free = start_free + i; return chunk_alloc(size, nobjs); } } end_free = 0; //调用一级的尝试获取 start_free = (char*)malloc_Alloc::allocate(bytes_toget); } heap_size += bytes_toget; end_free = start_free + bytes_toget; return (chunk_alloc(size, nobjs)); }}
阅读全文
0 0
- 【STL】STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- 【STL】空间配置器
- STL空间配置器
- STL----空间配置器
- STL-空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL空间配置器
- STL-空间配置器
- STL空间配置器
- STL空间配置器
- 【STL】空间配置器
- STL空间配置器
- STL空间配置器
- 如何使用PD10虚拟机安装ubuntu
- hrbust 1492 二分图匹配
- 理解高并发(2).我对并发编程的理解
- 9个最佳的大数据处理编程语言
- [字符串HASH][复杂度分析] NOI2017 .Day1 T2 蚯蚓排队
- STL空间配置器
- MNIST机器学习入门
- 理解高并发(3).多线程开发常见问题示例
- SSM整合
- JavaSE编程基础 第一章 初识Java
- windows下全文检索引擎sphinx/coreseek的安装配置
- 我实习在青岛
- kali linux 2016 配置ssh 实现远程登录
- 理解高并发(4).死锁监测方法