//---------------------------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. SQLSERVER中的鬼影索引

    SQLSERVER中的鬼影索引 看这篇文章之前可以先看一下鬼影记录 了解了解一下SQLSERVER里的鬼影记录关于鬼影记录的翻译一关于鬼影记录的翻译二 当删除表中的某一条记录的时候,索引页面的对应记录 ...

  2. jdk1.8配置环境变量

    1. 准备好jdk安装文件,选择地址,假设使用默认地址 2. 安装jdk,此时跳出安装 jre 的地址 3. 等待安装 4.找到安装路径,选择jdk 5. 复制文件夹下的bin 6. 点击我的电脑右键 ...

  3. jQuery为元素设置css的问题

    例子: 有如下的html代码 对文本框设置字体大小为20px ,即font-size:20px 首先会想到如下: $('input').css({font-size:'20px'}); 由于属性不能使 ...

  4. 转:SQL中 patindex函数的用法

    语法格式:PATINDEX ( '%pattern%' , expression ) 返回pattern字符串在表达式expression里第一次出现的位置,起始值从1开始算. pattern字符串在 ...

  5. windows的一些好用命令-自己总结:

    在win+R运行框中:     cmd:进入命令行界面     msconfig:可以查看“系统配置”     msinfo32:查看系统信息     services.msc打开"服务&q ...

  6. 【Alpha 冲刺】 5/12

    今日任务总结 人员 今日原定任务 完成情况 遇到问题 贡献值 胡武成 建立数据库 未完成 设计表结构的时候,有些逻辑没有设计好,重新review一番设想的功能才初步确定表结构 孙浩楷 根据UI设计, ...

  7. [BUG]自己的bug自己解,记一次在变量使用过程引发的bug

    [实现的功能要求]在短信编辑界面,将所有的emoji表情全部插入到编辑区域,其中表情共有5页,每遍历完一页时需要自动翻页重新获取表情并插入,在第5页中只有10个表情 下面先看看这段代码,大家能否看出有 ...

  8. 深入学习css之background属性

    css中允许应用纯色作为背景,也允许使用图片作为背景. background一共有8个对应的属性: 1.background-color:颜色值 用于设定背景的颜色 有3种定义颜色的形式, 1, 颜色 ...

  9. 自带hyper -v 或者 Vmware安装Linux centos

    centos系统存在网盘,链接: https://pan.baidu.com/s/1A5ywyLjIegcftaT_xCvPbA 密码: n6v4 https://blog.csdn.net/nanc ...

  10. [C++] set与multiset的常用函数

    参考资料:[C++ STL]Set和Multiset set 与 multiset set不允许重复 multiset允许重复 例: set : 1 2 3 4 5 6 multiset : 1 2 ...