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));    }}
原创粉丝点击