STL中的空间配置器(2)

当free list中没有可用区块时,调用refill()为free list填充空间,新的空间取自内存池(由chunk_alloc()完成)。如果内存池不够,则malloc之,如果系统heap空间也不够,chunk_alloc()就寻找还有空闲区块的free list并将其内存充公,如果还是不够就调用第一级配置器。第一级配置器有实现new-handler机制,内存不够会抛出异常。

#ifndef _DEFAULT_ALLOC_H
#define _DEFAULT_ALLOC_H

namespace Chenstl{   
    //使用内存池以减少碎片
    class default_alloc {
    private:
        enum { ALIGN = 8};
        enum { MAX_BYTES = 128 };
        enum { NFREELISTS = 16 };
        //static const int ALIGN = 8;
        //static const int MAX_BYTES = 128;
        //static const int NFREELISTS = 16;    //MAX_BYTES/ALIGN
        union obj {            //free-lists的节点构造
            union obj *next;
            char client[1];
        };
        //freelist
        static obj *free_list[NFREELISTS];
        static char *start_free;    //内存池的起始位置
        static char *end_free;        //内存池的终止位置
        static size_t heap_size;

private:
        //将bytes上调至8的倍数
        static size_t ROUND_UP(size_t bytes) {
            return ((bytes +ALIGN - 1) & ~(ALIGN - 1));
        }
        //获取合适的区块在freelist中的位置
        static  size_t FREELIST_INDEX(size_t __bytes) {
            return (((__bytes)+(size_t)ALIGN - 1) / (size_t)ALIGN - 1);
        }
        //返回一个大小为n的对象,并可能加入大小为n的其他区块到free-list
        static void *refill(size_t n);
        //配置一大块空间,可容纳nobjs个大小为size的区块
        //如果配置nobjs个区块有所不便,nobjs可能会降低
        static char *chunk_alloc(size_t size, int &nobjs);

public:
        static void *allocate(size_t n);
        static void deallocate(void *p, size_t n);
        static void *realloc(void *p, size_t old_sz, size_t new_sz);
    };
}

#endif

default_alloc.h

---------------------------------------------------------

#include "default_alloc.h"
#include "malloc_alloc.h"
using namespace Chenstl;

default_alloc::obj *default_alloc::free_list[NFREELISTS]
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
char *default_alloc::start_free = 0;    //内存池的起始位置
char *default_alloc::end_free = 0;        //内存池的终止位置
size_t default_alloc::heap_size = 0;

void *default_alloc::allocate(size_t n)
{
    obj *result = 0;
    obj **my_free_list = 0;
    if (n > MAX_BYTES)
        return malloc_alloc::allocate(n);
    //寻找free lists中合适的一个               
    my_free_list = free_list + FREELIST_INDEX(n);
    result = *my_free_list;
    if(0 == result)
    {//没有找到可用的freelist,从内存池里取出空间
        return refill(ROUND_UP(n));
    }
    //调整freelist
    *my_free_list = result->next;
    return result;
}

void default_alloc::deallocate(void *p, size_t n)
{

}
//返回一个大小为n的对象,并可能加入大小为n的其他区块到freelist
//在ANSI c中,void *不允许进行加减操作,所以chunk用char *
void *default_alloc::refill(size_t n)
{
    int objs = 20;
    char *chunk = chunk_alloc(n, objs);
   
    obj *next, *current;
    obj *result;
    obj **my_free_list;
    if (1 == objs)    //只取出一个区块
        return chunk;
    my_free_list = free_list + FREELIST_INDEX(n);
    result = (obj *)chunk;    //这一块返回给客户端
    //将freellist指向分配的区域
    *my_free_list = next = (obj *)chunk + n;
    for (int i = 1;; i++)
    {
        current = next;
        next = (obj *)((char *)next + n);    //这里注意不能直接用next+n
        if (i == objs - 1)
        {
            current->next = 0;
            break;
        }
        else
            current->next = next;
    }
    return result;   
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/102b355f40f3daf6aefb7bdbde8845d7.html