STL 二级配置器

一,二级配置器的源代码

enum{_ALIGN = 8};                       //小型区块的上调边界
enum{_MAX_BYTES = 128};                 //小型区块的上界
enum{_NFREELISTS = _MAX_BYTES/_ALIGN};  //free-lists 个数

/**
*  第一个参数用于多线程环境,第二个参数完全没有派上用场
*/
template<bool threads, int inst>
class _default_alloc_template{
private:
    //free list的节点
    union obj{
        union obj *free_list_link;
        char client_data[1];
    };
    //16 个free-lists
    static obj *volatile free_list[_NFREELISTS];
    //返回一个大小为n的对象,并可能加入大小为n的其他区块到free-list中
    static void *refill(size_t n);
    //配置一大块空间,可容纳nobjs个大小为size的区块
    static char *chunk_alloc(size_t size, int &nobjs);
    //内存池起始位置,只在chunk_alloc()中变化
    static char *start_free;
    //内存池结束位置,只在chunk_alloc()中变化
    static char *end_free;
public:
    static void *allocate(size_t n);
    static void deallocate(void *p, size_t n);
    static void *reallocate(void *p, size_t old_sz, size_t new_sz);
};

/**
*  空间配置器
*
*  此函数首先判断区块的大小,大于128byte就调用一级配置器,小于128byte就检查对应的
*  free-lists。如果free-lists内有可用的区块,就直接拿来使用,如果没有可用区块,就
*  把区块的大小上调至8的倍数,然后准备调用refill()准备为free-lists重新填充空间。
*/
template<bool threads, int inst>
static void *_default_alloc_template<threads, inst>::allocate(size_t n){
    obj * volatile *my_free_list;
    obj *result;
    //大于128就调用第一级配置器
    if(n > _MAX_BYTES){
        return (malloc_alloc::allocate(n));
    }
    //寻找16个free-lists中适当的一个
    my_free_list = free_list + FREELIST_INDEX(n);
    result = *my_free_list;
    if(result == 0){
        //没有找到可用的区块,准备填充free-lists
        void *r = refill(ROUND_UP(n));
        return r;
    }
    //调整free-lists
    *my_free_list = result->free_list_link;
    return (result);
}

/**
*  空间释放器
*
*  此函数首先判断区块大小,大于128byte就调用第一级配置器,小于128byte就找出对应的
*  free-lists,将区块回收。
*/
template<bool threads, int inst>
static void _default_alloc_template<threads, inst>::deallocate(void *p, size_t n){
    obj * volatile *my_free_list;
    obj *result;
    //大于128byte就调用第一级配置器
    if(n > (size_t)_MAX_BYTES){
        malloc_alloc::deallocate(p, n);
        return;
    }
    //寻找对应的feee-lists
    my_free_list = free_list + FREELIST_INDEX(n);
    //调整free-lists,回收区块
    q->free_list_link = *my_free_list;
    *my_free_list = q;
}


二,重新填充free-lists

二级配置器使用allocate()配置内存,当它发现free-lists中没有可用的区块时,就调用refill(),准备为free-lists重新填充空间。新的空间将取自内存池(经由chunk_alloc()完成),缺省取得20个新的节点(新区块),但万一内存池空间不够,获得的节点数可能小于20。


三,内存池

从内存池中取空间给free-lists使用,是chunk_alloc()函数的工作。chunk_alloc()函数以end_free - start_free来判断内存池的水量。如果水量充足,就直接调出20个区块返回给free-lists使用。如果水量不足以提供20个区块,但足够供应一个以上的区块,就拨出这不足20个区块的空间出去。如果内存池连一个区块空间都无法供应,此时便使用malloc()从heap中配置内存,为内存池注入源头活水以应付需求。新水量的大小为需求量的两倍,再加上一个随着配置次数增加而越来越大的附加量。万一heap空间不够用,malloc()失败,就调用第一级配置器,第一级配置器也是使用malloc()来配置内存,但它有out-of-memory处理机制,或许有机会可以释放掉其他内存拿来此处使用。如果可以就成功,否则抛出bad_alloc异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值