第一级配置器是对C的内存分配函数malloc,free,realloc的简单封装,用来分配大于128bytes的区块。

第二级配置器管理16个free-lists链表,各自管理8-128bytes的小额区块。

链表节点结构如下:

union obj //free_list节点
{
union obj* free_list_link;
};

当一个区块未被使用时,其前端sizeof(obj)的空间用于存放union obj,因此可通过free_list_link指针找到下一个区块。

当需要一个区块时,直接将该区块的首地址(即指向该区块的free_list_link)返回,使用过程中,该区块的前部union被覆盖,因此不会造成空间的浪费。

代码如下:

class alloc
{
private:
static size_t ROUND_UP(size_t bytes) //将bytes上调至8的倍数
{
return (((bytes)+__ALIGN - )&~(__ALIGN - ));
}
private:
union obj //free_list节点
{
union obj* free_list_link;
};
private:
static obj* volatile free_list[__NFREELISTS];
static size_t FREELIST_INDEX(size_t bytes)
{
return (((bytes)+__ALIGN - ) / __ALIGN - );
}
static void* refill(size_t n); //返回大小为n的对象,并可能加入大小为n的其他区块到free_list
static char* chunk_alloc(size_t size, int &nodejs); static char* start_free; //内存池起始
static char* end_free; //内存池结束
static size_t heap_size; //? public:
static void* allocate(size_t n);
static void deallocate(void* p, size_t n);
static void* reallocate(void* p, size_t old_sz, size_t new_sz); }; char* alloc::start_free = ;
char* alloc::end_free = ;
size_t alloc::heap_size = ;
alloc::obj* volatile alloc::free_list[__NFREELISTS] = { nullptr }; void* alloc::allocate(size_t n)
{
obj* volatile* my_free_list; // volatile修饰的是*my_free_list
obj* result;
if (n > static_cast<size_t>(__MAX_BYTES))
{
return malloc(n);
} my_free_list = free_list + FREELIST_INDEX(n);
result = *my_free_list;
if (result == nullptr) //没找到可用free_list
{
void* r = refill(ROUND_UP(n));
return r;
}
*my_free_list = result->free_list_link;
return result;
}
void alloc::deallocate(void* p, size_t n)
{
obj* q = (obj*)p;
obj* volatile* my_free_list; if (n > (size_t)__MAX_BYTES)
{
free(p);
return;
}
my_free_list = free_list + FREELIST_INDEX(n);
q->free_list_link = *my_free_list;
*my_free_list = q;
}
void* alloc::refill(size_t n)
{
int nobjs = ;
char* chunk = chunk_alloc(n, nobjs);
obj* volatile* my_free_list;
obj* result;
obj* current_obj, *next_obj;
if (nobjs == )return (chunk);
my_free_list = free_list + FREELIST_INDEX(n);
result = (obj*)chunk; //这一块返回给客端
*my_free_list = next_obj = next_obj = (obj*)(chunk + n); //chunk~chunk+n已经分配给客户端
//将free list的各节点串接起来 for (int i = ;; ++i)
{
current_obj = next_obj;
next_obj = (obj*)((char*)next_obj + n);
if (nobjs - == i)
{
current_obj->free_list_link = nullptr;
break;
}
else
{
current_obj->free_list_link = next_obj;
}
}
return result;
}
char* alloc::chunk_alloc(size_t size, int& nobjs) //尝试从内存池分配单个大小为size,数量为nobjs的区块
{
char* result;
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;
}
else if (bytes_left>=size) //不能完全满足需求,但能供应>=1个区块
{
nobjs = bytes_left / size;
total_bytes = size*nobjs;
result = start_free;
start_free += total_bytes;
return result;
}
else
{
size_t bytes_to_get = * total_bytes + ROUND_UP(heap_size >> );
if (bytes_left > )
{
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); //配置heap空间
if (start_free == nullptr) //heap空间不足
{
obj* volatile* my_free_list, *p;
for (int i = size; i <= __MAX_BYTES; i += __ALIGN) //寻找尚未使用的足够大(至少>=size)的区块,
{
my_free_list = free_list + FREELIST_INDEX(i); //寻找大小为i的区块所在地
p = *my_free_list;
if (p)
{
*my_free_list = p->free_list_link; //将该区块取出
start_free = (char*)p; //将其编入内存池
end_free = start_free + i;
return chunk_alloc(size, nobjs); //递归调用,修正nobjs
}
}
end_free = ; //彻底没内存
throw; //抛出异常
}
heap_size += bytes_to_get; //从堆里获取的空间
end_free = start_free + bytes_to_get;
return (chunk_alloc(size, nobjs));
}
}

【C++】SGI-STL空间配置器的更多相关文章

  1. 【转】STL空间配置器

    STL空间配置器(allocator)在所有容器内部默默工作,负责空间的配置和回收.STL标准为空间配置器定义了标准接口(可见<STL源码剖析>P43).而具体实现细节则由各编译器实现版本 ...

  2. STL——空间配置器(构造和析构基本工具)

    以STL的运用角度而言,空间配置器是最不需要介绍的东西,它总是隐藏在一切组件(更具体地说是指容器,container)的背后,默默工作,默默付出.但若以STL的实现角度而言,第一个需要介绍的就是空间配 ...

  3. STL空间配置器

    1.什么是空间配置器? 空间配置器负责空间配置与管理.配置器是一个实现了动态空间配置.空间管理.空间释放的class template.以内存池方式实现小块内存管理分配.关于内存池概念可以点击:内存池 ...

  4. 咬碎STL空间配置器

    STL空间配置器 一.开场白: 给我的感觉就是,了解是空间配置器的功能,是那么的明了:在看原理,我还是很开心:接下来是360度大转变: 那么长的变量或者函数命名.那么多的宏.不爽,不过,遇上我这种二货 ...

  5. STL——空间配置器(SGI-STL)

    一. 空间配置器标准接口 参见<STL源码剖析>第二章-2.1.<memory>文件. 二.具备次配置力的SGI空间配置器 1. SGI STL的配置器与众不同,也与标准规范不 ...

  6. stl空间配置器简介

    1. 符合STL标准的空间配器接口 STL是c++中使用非常广泛的一个标准库,它包含各种有用的容器.而空间配置器作为STL各种容器的背后的核心,负责容器内部内存的分配和释放.不过空间配置器可以分配的也 ...

  7. 【陪你系列】5 千字长文+ 30 张图解 | 陪你手撕 STL 空间配置器源码

    大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub https://github.com/rongweihe/MoreT ...

  8. stl空间配置器线程安全问题补充

    摘要 在上一篇博客<STL空间配置器那点事>简单介绍了空间配置器的基本实现 两级空间配置器处理,一级相关细节问题,同时简单描述了STL各组件之间的关系以及设计到的设计模式等. 在最后,又关 ...

  9. STL空间配置器那点事

    STL简介 STL(Standard Template Library,标准模板库),从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其 ...

  10. STL空间配置器解析和实现

    STL空间配置器的强大和借鉴作用不言而喻,查阅资料,发现了Dawn_sf已经对其有了极其深入和详细的描述,所以决定偷下懒借用其内容,只提供自己实现STL空间配置器的源码,具体解析内容参考:(一)STL ...

随机推荐

  1. python3基础:基本语句(2017)

    http://www.cnblogs.com/qq21270/p/4591318.html  字符串.文本文件 http://www.cnblogs.com/qq21270/p/7872824.htm ...

  2. apt-get 使用指南

    # apt-get update——在修改/etc/apt/sources.list或者/etc/apt/preferences之後运行该命令.此外您需要定期运行这一命令以确保您的软件包列表是最新的. ...

  3. php-- orther

    0.PHP实现物流查询(通过快递网API实现) 1.php7 新特性 2.php的精确计算 3.PHP大小写是否敏感问题的汇总 4.取得类的 对象属性名 和类的属性 和类的方法名 5.php判断 != ...

  4. zabbix使用ICMP Ping模版实现对客户端网络状态的监控,监控丢包率、响应时间

    参考网站: https://www.cnblogs.com/saneri/p/6706578.html 使用fping报错注意事项: https://blog.csdn.net/oqqssh/arti ...

  5. django之block extend标签

    class ExtendsNode(Node): must_be_first = True context_key = 'extends_context' def __init__(self, nod ...

  6. python_03 各种运算符

    1.算数运算 2.比较运算 3.赋值运算 4.逻辑运算 先计算括号中表达式 计算顺序:and,or,not在一个表达式中从前到后计算, 若and前一个元素为false则立刻返回为False,不计算后面 ...

  7. as2 连接服务器 post

    import mx.utils.Delegate; //接收服务器数据的文本加载器 var result_lv:LoadVars; /** * 数据提交成功后 * 获取的数据 * @param suc ...

  8. 2312--1.3.4 Prime Cryptarithm 牛式

    Description 下面是一个乘法竖式,如果用我们给定的那n个数字来取代*,可以使式子成立的话,我们就叫这个式子牛式. * * * x * * ------- * * * * * * ------ ...

  9. 尚硅谷springboot学习16-slf4j的使用

    如何在系统中使用SLF4j 以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法: 给系统里面导入slf4j的jar和 logback的实现jar impor ...

  10. App.js实现使用js开发app的应用,此文是中文文档

    在阅读前,在此说明下,本人英文一直不好,所以该文档是借助翻译工具翻译的,阅读起来可能有点不好,请各位谅解,哪位大神有标准的中文文档请分享下 Github下载地址:https://github.com/ ...