template <int inst>
class __malloc_alloc_template
{
private:
static void* oom_malloc(size_t);
static void* oom_realloc(void*, size_t);
static void (*__malloc_alloc_oom_handler)();
public:
static void* allocate(size_t n)
{
void* result = malloc(n);
if (0 == result) result = oom_malloc(n);
return result;
}
static void deallocate(void* p, size_t /* n */)
{
free(p);
}
static void* reallocate(void* p, size_t /* old_sz */, size_t new_sz)
{
void* result = realloc(p, new_sz);
if (0 == result) result = oom_realloc(p, new_sz);
return result;
}
static void (*set_malloc_handler(void (*f)()))()
{
void (*old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = f;
return(old);
}
};
void (* _malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
template <int inst>
void* __malloc_alloc_template<inst>::oom_malloc(size_t n)
{
void (*my_malloc_handler)();
void* result;
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = malloc(n);
if (result) return(result);
}
}
template <int inst>
void* __malloc_alloc_template<inst>::oom_realloc(void* p, size_t n)
{
void (*my_malloc_handler)();
void* result;
for (;;)
{
my_malloc_handler = __malloc_alloc_oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();
result = realloc(p, n);
if (result) return(result);
}
}
template<class T, class Alloc>
class simple_alloc {
public:
static T *allocate(size_t n)
{ return 0 == n? 0 : (T*) Alloc::allocate(n * sizeof (T)); }
static T *allocate(void)
{ return (T*) Alloc::allocate(sizeof (T)); }
static void deallocate(T *p, size_t n)
{ if (0 != n) Alloc::deallocate(p, n * sizeof (T)); }
static void deallocate(T *p)
{ Alloc::deallocate(p, sizeof (T)); }
};
enum { ALIGN = 8};//小型区块的上调边界
enum { MAXBYTES = 128};//小型区块的上限,超过的区块由malloc分配
enum { NFREELISTS = MAX_BYTES / ALIGN };//free-lists的个数为16
template <bool threads, int inst>
class __default_alloc_template {
private:
//free-lists的节点构造
union obj
{
union obj *next;
char client[1];
};
static obj *free_list[NFREELISTS];
private:
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));
}
//根据区块大小,决定使用第n号free-list,n从0开始计算
static size_t FREELIST_INDEX(size_t bytes)
{
return (((bytes)+ ALIGN - 1) / ALIGN - 1);
/*
若bytes为8,则(8+7)/8-1 = 0;
若bytes为16,则(16+7)/8-1 = 1;
若bytes为20,则(20+7)/8-1 = 2;
若bytes为24,则(24+7)/8-1 = 2;
*/
}
//返回一个大小为n的对象,并可能加入大小为n的其他区块到free-list
static void *refill(size_t n);
//配置一大块空间,可容纳nobjs个大小为size的区块
//如果配置nobjs个区块有所不便,nobjs可能会降低
static char *chunk_alloc(size_t size, size_t& nobjs);
public:
static void *allocate(size_t bytes);
static void deallocate(void *ptr, size_t bytes);
static void *reallocate(void *ptr, size_t old_sz, size_t new_sz);
};
}
空间配置器allocate函数:
static void* allocate(size_t n)
{
obj** my_free_list;
obj* result;
if (n > (size_t)__MAX_BYTES) //若n大于128,则采用第一级适配器
{
return(malloc_alloc::allocate(n));
}
//寻找16个链表中适当的一个
my_free_list = free_list + FREELIST_INDEX(n);
result = *my_free_list;
if (result == 0)
{
void* r = refill(ROUND_UP(n));
return r;
}
*my_free_list = result->free_list_link;
return (result);
};
重新填充free lists