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

}

}

stl源码剖析 详细学习笔记 空间配置器的更多相关文章

  1. stl源码剖析 详细学习笔记 配接器

    //---------------------------15/04/03---------------------------- /* 配接器概述: 1:adapter是一种设计模式:将一个clas ...

  2. stl源码剖析 详细学习笔记 hashtable

    //---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...

  3. stl源码剖析 详细学习笔记 set map

    // //  set map.cpp //  笔记 // //  Created by fam on 15/3/23. // // //---------------------------15/03 ...

  4. stl源码剖析 详细学习笔记 RB_tree (1)

    // //  RB_tree_STL.cpp //  笔记 // //  Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...

  5. stl源码剖析 详细学习笔记priority_queue slist

    // //  priority_queue.cpp //  笔记 // //  Created by fam on 15/3/16. // // //------------------------- ...

  6. stl源码剖析 详细学习笔记heap

    // //  heap.cpp //  笔记 // //  Created by fam on 15/3/15. // // //---------------------------15/03/15 ...

  7. stl源码剖析 详细学习笔记 算法(1)

    //---------------------------15/03/27---------------------------- //算法 { /* 质变算法:会改变操作对象之值 所有的stl算法都 ...

  8. stl源码剖析 详细学习笔记 算法总览

    //****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标 ...

  9. stl源码剖析 详细学习笔记 RB_tree (2)

    //---------------------------15/03/22---------------------------- //一直好奇KeyOfValue是什么,查了下就是一个和仿函数差不多 ...

随机推荐

  1. js经典应用

    一.js字符串转数字: 1.parseInt()和parseFloat()两个转换函数: 2.强制类型转换,Number(value)——把给定的值转换成数字(可以是整数或浮点数): 3.利用js变量 ...

  2. October 17th 2017 Week 42nd Tuesday

    We execuse our sloth under the pretext of difficulty. 我们常以困难为由,作为懒惰的借口. The process of my system-tra ...

  3. C#中单问号(?)和双问号(??)的用法整理

    1.单问号(?) 1.1 表示Nullable类型 C#2.0里面实现了Nullable数据类型 //A.比如下面一句,直接定义int为null是错误的,错误提示为无法将null转化成int,因为后者 ...

  4. Pre标签 自动换行

    <pre> 元素可定义预格式化的文本.被包围在 pre 元素中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre> 标签的一个常见应用就是用来表示计算机的源代码 ...

  5. 在Linux服务器上运行Jupyter notebook server教程

    在Linux服务器上运行Jupyter notebook server教程 很多deep learning教程都推荐在jupyter notebook运行python代码,方便及时交互.但只在本地运行 ...

  6. 实例化list

    List<String> lists = new ArrayList<String>();list.add("123");

  7. 在Word2007,2010,2016中分栏但不换页的方法

    解决方法: word2007:界面左上角的按钮->选择word选项->依次点击“高级”->“版式选项”->点开加号,“按word6.x/95/97的方式排放脚注”. Word2 ...

  8. 2-5 R语言基础 factor

    #因子:分类数据#有序和无序#整数向量+标签label#Male/Female#常用于lm(),glm() > x <- factor(c("female"," ...

  9. NOIP模拟赛-2018.10.22

    模拟赛 今天第一节课是历史,当然是不可能上的,一来到机房发现今天高二考试... 老师说以后可能还要给高一考...那还不如现在跟着做好了,毕竟在学长学姐中垫底显得没那么丢人 这套题风格挺奇怪的...为什 ...

  10. Docker实战(二)之操作Docker容器

    容器是Docker的另外一个核心概念.简单来说,容器是镜像的一个运行实例.所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层.如果认为虚拟机是模拟运行的一整套操作系统系统(包括内核,应 ...