STL源码——特殊的空间配置器
2016-12-14 11:57
288 查看
源代码展示:https://github.com/uagvdu/Memory/blob/STL-MyAllocate/MyAllocator.h
STL标准的空间配置器 就是将new和delete进行了简单的封装,这里不是重点,就懒得说了。而且这个标准的空间配置器也没被进行使用。
SGI特殊的空间配置器:
一级配置器的实现:
就是正常的malloc和free,但在此的基础上添加了一个事件处理:即针对于malloc返回值为NULL的情况,系统内存开辟失败的一些处理。
处理失败的内存分配要求的其他方法:编写自定义恢复例程来处理此类失败,然后通过调用 _set_new_handler 运行时函数来注册您的函数。/官方解释 /
设置一个函数句柄: 系统在内存配置需求无法被满足的情况下,调用一个你所指定的函数,
因为函数的每次调用都会消耗内存的空间,当函数返回又会释放内存。不断的进行调用,说不定就会有合适的内存。(废话多就知道是本人解释)
二级配置器:
最重要的还是二级配置器:而且这也算是 SGI 版本的内存池 :
/二级配置器简单来说就一两句话:一个指针数组存放自由链表头指针,自由链表指向对应的内存块,每一个数组成员含义是代表内存区块的大小,自由链表指向对应的内存块 /
思路: 1.如果所需区块<字节数>过大,超过128 bytes,则调用一级空间配置器进行处理.
上面的一二级配置器只是实现了空间的开辟和释放,SGI还为它包装了一个类 ,使配置器接口能够符合STL规格:
STL标准的空间配置器 就是将new和delete进行了简单的封装,这里不是重点,就懒得说了。而且这个标准的空间配置器也没被进行使用。
SGI特殊的空间配置器:
一级配置器的实现:
就是正常的malloc和free,但在此的基础上添加了一个事件处理:即针对于malloc返回值为NULL的情况,系统内存开辟失败的一些处理。
处理失败的内存分配要求的其他方法:编写自定义恢复例程来处理此类失败,然后通过调用 _set_new_handler 运行时函数来注册您的函数。/官方解释 /
设置一个函数句柄: 系统在内存配置需求无法被满足的情况下,调用一个你所指定的函数,
因为函数的每次调用都会消耗内存的空间,当函数返回又会释放内存。不断的进行调用,说不定就会有合适的内存。(废话多就知道是本人解释)
:malloc开辟空间失败的情况: typedef void(*ALLOC_HANDLER)();//定义一个函数句柄, static ALLOC_HANDLER __mallocAllocOomHandler; static void* OOM_Malloc(size_t n) { void* ret; while (1) { if (__mallocAllocOomHandler == NULL)//如果这个函数都不存在,代表系统一点空间都不会剩余,那么也就只能抛异常 { throw bad_alloc(); } else { //期望释放内存 (*__mallocAllocOomHandler)();//调用函数消耗内存,返回函数释放内存,一直循环下去,说不定就会有合适的空间被释放从而开辟出来需要的空间 ret = malloc(n); if (ret) { return ret; } } } }
二级配置器:
//先列出来一些成员变量 public: enum{ __ALIGN = 8 };// 基准值 enum{ __MAX = 128 }; //区块最大字节数; enum{ __BLOCKNUM = __MAX / __ALIGN}; //区块个数 protected: union Obj //共用体,省空间 { union Obj* _freelistlink; char _clientDate[1]; }; static Obj* _freelist[__BLOCKNUM]; //存放自由链表的指针数组 // Chunk allocation state. static char* _start_free; //大块的首地址 static char *_end_free; //大块的尾地址 static size_t _heap_siz; //附加量,开辟所需大小的内存池的时候附加的内存空间
最重要的还是二级配置器:而且这也算是 SGI 版本的内存池 :
/二级配置器简单来说就一两句话:一个指针数组存放自由链表头指针,自由链表指向对应的内存块,每一个数组成员含义是代表内存区块的大小,自由链表指向对应的内存块 /
思路: 1.如果所需区块<字节数>过大,超过128 bytes,则调用一级空间配置器进行处理.
2.当所需区块<字节数>小于128bytes时,则需要求得其所对应的区块位置。< free_list成员为8的倍数,数组每个成员代表区块的大小 > 3.找到对应的位置然后查找该处是否有剩余的区块,若有,则直接从free_list对应的位置中拨出区块,因为是链表,所以记得要指向下一个位置。若没有,则需要调用refill(),准备为free_list重新填充区块,新的空间将取自内存池。 4.内存池的空间:refill()重新填充给free_list时,要看内存池的大小 ,若内存池 小于一个区块:连一个所需要的区块都没有,就只能进行重新开辟 大于一个区块:返回chunk,内存池chunk之后的内存池经过分割对应的区块大小之后连在free_list中 等于一个区块:直接返回chunk,也不用在free_list中添加区块,因为其初始值就是NULL; 5.有申请就会有释放:当释放的区块<字节数> 大于128bytes时,就调用一级空间配置器进行处理,否则就直接连在free_list对应的位置中。<头插>
上面的一二级配置器只是实现了空间的开辟和释放,SGI还为它包装了一个类 ,使配置器接口能够符合STL规格:
template<class T,class _alloc> class SimpleAlloc //仅仅只是空间配置器的接口 { public: static T* allocate() //单个对象 { T* dst = _alloc::Allocate(sizeof(T)); return dst; } static T* allocate(size_t n )//多个对象或者数组, { T* dst = _alloc::Allocate(n*sizeof(T)); return 0==n? 0:dst; } static void deallocate(T* ptr,size_t n) { if (n != 0) _alloc::Deallocate(ptr, n*sizeof(T)); } static void deallocate(T* ptr) { _alloc::Deallocate(ptr, n*sizeof(T)); } };
其内部函数知识单纯的转调用,调用传递给配置器,这个接口使配置器的配置单位从字节数转为个别元素的大小,或者元素的个数。SGI STL容器全部都是用这个simple_alloc接口。
相关文章推荐
- STL源码学习——空间配置器
- STL空间配置器源码及其分析
- STL源码笔记之空间配置器
- STL源码分析--第二级空间配置器
- STL源码笔记之空间配置器
- STL源码剖析学习二:空间配置器(allocator)
- STL源码:空间配置器(一)SGI的空间配置器
- 《STL 源码剖析》之空间配置器
- STL之空间配置器源码(框架)剖析
- STL 源码剖析读书笔记一:空间配置器
- STL中的空间配置器allocator的实现原理及源码剖析
- STL源码学习之空间配置器allocator【2013.11.15】
- STL源码解析笔记(1)--空间配置器
- STL学习_SGI空间配置器_第一级配置器源码分析
- STL源码剖析学习笔记之具备次配置力(sub-allocation)的SGI空间配置器
- STL源码分析--空间配置器的底层实现 (二)
- C++ STL源码解析:空间配置器allocator分析
- STL学习_SGI二级空间配置器源码剖析
- STL深入探究(一、空间配置器)
- 【STL】实现简单的空间配置器