//---------------------------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. UIButton vs UIEventListener 事件处理

    NGUI的事件 在使用NGUI的事件处理时,发现UIButton和UIEventListener之间的共同点越来越多. 当然处理事件,也有一些其它的函数,比如:UIEventTrigger,Butto ...

  2. Linux 配置 hosts

    1. hosts 是什么 维基百科对 hosts 的介绍如下: hosts文件(域名解析文件)是一个用于储存计算机网络中各节点信息的计算机文件. 这个文件负责将主机名称映射到相应的IP地址. host ...

  3. MySQL案列之主从复制出错问题以及pt-slave-restart工具的使用

    今天主从复制遇到一个问题,主库上插入了几百行万数据,后来又删除了这些数据,原因就是主库删除的表从库中不存在,导致从库在遇到删除不存在表的错误无法继续同步. MySQL [(none)]> sho ...

  4. /etc/sudoers文件的分析以及sudo的高级用法

    高级用法总结: sudo命令是普通用户的提权操作指令.在权限控制中,我们可以使用/etc/sudoers文件中来进行设置.基本的用法比较熟悉.比如设置一个普通用户可拥有root用户的运行权限,那么设置 ...

  5. 不使用 vue-cli 与 vue 模版,使用 Vue2.x + webpack4.x 从零开始一步步搭建项目框架

    说明 这是我根据慕课网上的一个课程 Vue+Webpack打造todo应用 过程一步步搭下来的框架,去掉了业务相关的逻辑. 项目最终的效果包括了引入vue框架:使用CSS预处理器:使用babel:引用 ...

  6. C++基础算法学习——生理周期

    人有体力.情商.智商的高峰日子,它们分别每隔23天.28天和33天出现一次.对于每个人,我们想知道何时三个高峰落在同一天.给定三个高峰出现的日子p,e和i(不一定是第一次高峰出现的日子),再给定另一个 ...

  7. October 13th 2017 Week 41st Friday

    The shortest distance between two people is a smile. 人与人之间最短的距离是微笑. I find a smiling face can bring ...

  8. css常见知识点

    1.内核区分 希望某一个浏览器能一统江湖 -ms-transform:rotate(7deg); //-ms代表ie内核识别码 -moz-transform:rotate(7deg); //-moz代 ...

  9. Gitkraken的使用

    一个优秀的团队合作离不开git,一个优秀的程序员也离不开git.gitkraken是我在进行软工实践这门课接触到的git的UI界面的工具,它给我留下的印象就是非常好用和方便 怎么个方便法呢? 方便的安 ...

  10. post-message-stream的学习-metamask

    kumavis/post-message-stream post-message-stream Sets up a duplex object stream over window.postMessa ...