STL源码——特殊的空间配置器

源代码展示:https://github.com/uagvdu/Memory/blob/STL-MyAllocate/MyAllocator.h

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接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值