stl源码剖析 详细学习笔记 空间配置器

//---------------------------15/04/05----------------------------

/*

空间配置器概述:

1:new操作包含两个阶段操作

1>调用::operator new配置内存(底层使用malloc来申请内存)。

2>调用函数的构造函数,构造对象内容。

delte和new一样,先调用析构函数,再调用::operator delete释放内存。

2:为了效率,stl把两个阶段分开来。

1>内存配置操作: alloc::allocate();

2>内存释放操作: alloc::deallocate();

3>对象构造操作: ::construct();

4>对象析构操作: ::destory();

3:内存配置器的整体:

1><stl_construct.h>     : 这里定义了全局函数construct()和的destroy()。

2><stl_alloc.h>         : 定义了一二级配置器。

3><stl_uninitialized.h> : 定义了一些全局函数,用来填充或复制大块内存数据。

un_initialized_copy(), un_initialized_fill(), un_initialized_fill_n()

这些函数对效率考虑得面面俱到:最差的情况下会调用construct(),最佳的情况下会

使用c的标准函数memmove()直接进行内存数据的移动。

*/

//construct() 和 destroy()

template<class T1,
class T2>

inline
void construct(T1* p,
const T2& value)

{

new (p) T1(value);

}

template<class T>

inline
void destroy(T* pointer)

{

pointer->~T();

}

template<class ForwardIterator>

inline
void destroy(ForwardIterator first, ForwardIterator last)

{

__destroy(first, last, value_type(first));

}

template<class ForwardIterator,
class T>

inline
void __destroy(ForwardIterator first, ForwardIterator last, T*)

{

typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;

__destroy_aux(first, last, trivial_destructor());

}

template<class ForwardIterator>

inline void

__destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)

{

for(; first < last; ++first)

destroy(&*first);

}

template<class ForwardIterator>

inline
void __destroy_aux(ForwardIterator, ForwardIterator, __true_type) {}

inline
void destroy(char*,
char*) {}

inline void destroy(wchar_t*,
wchar_t*) {}

//alloc

template<class T,
class Alloc>

class simple_alloc

{

public:

static T* allocate(size_t n)

{

== n ?
: (T*) Alloc::allocate(n *
sizeof(T));

}

static T* allocate(void)

{

return (T*) Alloc::allocate(sizeof(T));

}

static void deallocate(T *p, size_t n)

{

!= n)

Alloc::deallocate(p, n *
sizeof(T));

}

static void deallocate(T *p)

{

Alloc::deallocate(p,
sizeof(T));

}

};

//第一级配置

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:

//直接调用malloc分配内存,失败就调用oom_malloc,这个函数会不断申请分配,

//并不断调用处理函数,如果没有处理函数,就抛出错误。

static void* allocate(size_t n)

{

void *result = malloc(n);

== result)

result == oom_malloc(n);

return result;

}

static void deallocate(void *p, size_t)

{

free(p);

}

static void* reallocate(void *p, size_t, size_t new_sz)

{

void *result = realloc(p, new_sz);

== result)

result = oom_realloc(p, new_sz);

return result;

}

static void (* set_malloc_handle(void (*f)()))()

{

void ( *old)() = __malloc_alloc_oom_handler;

__malloc_alloc_oom_handler = f;

return(old);

}

};

template<int inst>

void ( *__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() =
;

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;

== my_malloc_handler)

{

__THROW_BAD_ALLOC;

}

(*my_malloc_handler)();

result = malloc(n);

if(result)

return (result);

}

}

template<int inst>

void* __malloc_alloc_oom_handler<int>::oom_realloc(void *p, size_t n)

{

void ( *my_malloc_handler());

void *result;

for(; ;)

{

my_malloc_handler = __malloc_alloc_oom_handler;

== my_malloc_handler)

{

__THROW_BAD_ALLOC;

}

(*my_malloc_handler)();

result = realloc(p, n);

if(result)

return (result);

}

}

> malloc_alloc;

//第二级配置器

//使用union节省空间

union obj

{

union obj * free_list_link;

];

};

enum { __ALIGN =
};

enum { __MAX_BYTES =
};

enum { __NFREELISTS = __MAX_BYTES / __ALIGN};

template<bool threads,
int inst>

class __default_alloc_template

{

private:

//这里就是加7再对8取模
这样写的公式扩展性比较小, 也就是__ALIGN必须取2的倍数,

//不然这公式就不是取模操作了。

static size_t ROUND_UP(size_t bytes)

{

) & ~(__ALIGN - ));

}

union obj

{

union obj *free_list_link;

];

};

static obj * volatile free_list[__NFREELISTS];

static size_t FREELIST_INDEX(size_t bytes)

{

) / __ALIGN - ));

}

static void* refill(size_t n);

static char *chunk_alloc(size_t size,
int &nobjs);

static char *start_free;

static char *end_free;

static size_t heap_size;

public:

static void* allocate(size_t n)

{

obj *
volatile * my_free_list;

obj * result;

if(n > (size_t)__MAX_BYTES)

return (malloc_alloc::allocate(n));

my_free_list = free_list + FREELIST_INDEX(n);

result = *my_free_list;

)

{

void *r = refill(ROUND_UP(n));

return r;

}

*my_free_list = result->free_list_link;

return (result);

}

//如果比最大大小大,就交给第一级配置,否则收回到链表中

static void deallocate(void *p, size_t n)

{

obj *q = (obj*)p;

obj *
volatile * my_free_list;

if(n > (size_t)__MAX_BYTES)

{

malloc_alloc::deallocate(p, n);

return;

}

my_free_list = free_list + FREELIST_INDEX(n);

q->free_list_link = *my_free_list;

*my_free_list = q;

}

static void* reallocate(void *p, size_t old_sz, size_t new_sz);

};

template<bool threads,
int inst>

char *__default_alloc_template<threads, inst>::start_free =
;

template<bool threads,
int inst>

char *__default_alloc_template<threads, inst>::end_free =
;

template<bool threads,
int inst>

size_t *__default_alloc_template<threads, inst>::heap_size =
;

template<bool threads,
int inst>

__default_alloc_template<threads, inst>::obj *volatile

__default_alloc_template<threads, inst>::free_list[__NFREELISTS] =

{,
, , , , ,
, , , , ,
, , , , };

template<bool threads,
int inst>

void* __default_alloc_template<threads, inst>::refill(size_t n)

{

//20个节点

;

//申请20个节点,会修改nobjs的值,也就是申请到多少个节点

char *chunk = chunk_alloc(n, nobjs);

obj *
volatile * my_free_list;

obj *result;

obj *current_obj, *next_obj;

int i;

//如果只申请到一个节点,直接返回

== nobjs)

return (chunk);

//找到n大小节点的位置

my_free_list = free_list + FREELIST_INDEX(n);

//第一个节点是用来返回的,不用存入链表中

result = (obj*)chunk;

//链表的第一个节点就是下一个节点

*my_free_list = next_obj = (obj*)(chunk + n);

; ; i++)

{

//当前节点是下一个节点

current_obj = next_obj;

//下一个节点是下下个节点

next_obj = (obj*)((char*)next_obj + n);

//如果是最后的节点了,就设置下个节点为0,并返回,否则好设置下一个节点

== i)

{

current_obj->free_list_link =
;

break;

}

else

{

current_obj->free_list_link = next_obj;

}

}

//把申请到的第一个节点返回

return (result);

}

template<bool threads,
int inst>

char* __default_alloc_template<threads, inst>::

chunk_alloc(size_t size,
int& nobjs)

{

char *result;

//需要的总大小(bytes)

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);

}

//如果剩下的大小大于一个size,
就返回最大的内存大小

else if(bytes_left >= size)

{

nobjs = bytes_left / size;

total_bytes = size * nobjs;

result = start_free;

start_free += total_bytes;

return (result);

}

//一个都没有

else

{

//算出需要的内存大小,2倍的需求量+现有大小的1/16(需要调整)。

size_t bytes_to_get =
* total_bytes + ROUND_UP(heap_size >> );

//先把内存池中剩余的空间中的内存取出放入链表中

)

{

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;

}

//申请内存

start_free = (char*)malloc(bytes_to_get);

== start_free)

{

//无法正常申请内存

int i;

obj *
volatile * my_free_list, *p;

//尝试拆分大节点

for(i = size; i <= __MAX_BYTES; i += __ALIGN)

{

//找到比要申请的内存大一点的节点,可以把他拆分掉

my_free_list = free_list + FREELIST_INDEX(i);

//让p等于这个链表的第一个节点

p = *my_free_list;

!= p)

{

//如果有节点,就把这个节点放入内存池中

*my_free_list = p->free_list_link;

start_free = (char*)p;

end_free = start_free + i;

return (chunk_alloc(size, nobjs));

}

}

//如果找不到大的节点,只能调用第一级配置,调用客户设置的处理函数了。

end_free =
;

start_free = (char*)malloc_alloc::allocate(bytes_to_get);

}

//内存池大小调整

heap_size += bytes_to_get;

end_free = start_free + bytes_to_get;

return (chunk_alloc(size, nobjs));

}

}

上一篇:Full GC有关问题学习分析(转载)


下一篇:防止sql注入 参数化解决方案