空间适配器既是分配内存或者硬盘空间的组件,因为STL的操作对象都存放在容器里,容器是需要配置空间的。
SGI 版本的标准的空间配置器
SGI 版标准的空间配置器,基本只是通过 ::operator new 和 ::operator delete 的薄薄一层封装实现的,基本上没有效率上的强化。
::operator new 和 new 的区别:
new:new的昨天是分配内存+调用构造函数初始化。
::opetarot new:调用一个函数来完成必需的内存分配,它对构造函数一无所知,类似malloc();
类似:
void * operator new(size_t size);
SGI特殊的空间配置器
构造和析构的工具
//construct:
template <class T1, class T2>
inline void construct(T1 *p, const T2& value) {
new (p) T1(value);
}
//destory
//destory 有两个版本,分别是 接收一个指针,和接收两个迭代器
//接收一个指针
template <class T1>
inline void destory(T1 *pointer) {
pointer->~T();
}
//
template <class ForwardIterator>
inline void destory(ForwardIterator first, ForwardIterator last, T*) {
/*利用typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor,
判断类型T的析构是否存在特性,并调用__destroy_aux,传入trivial_destructor*/
typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
/*
若存在特性,则会调用到__destroy_aux(Iterator, Iterator, __false_type), 并逐一对[first, last)范围内的元素进行析构
若不存在特性,则会调用到__destroy_aux(Iterator, Iterator, __true_type), 并什么都不做
*/
__destory_aux(first, last, trivial_destructor());
}
//
空间的配置与释放,std:alloc
__malloc_alloc_template 是第一级配置器,__default_alloc_template是第二级配置器。二级配置器维护了16个自由链表,负责小型区块的配置能力。当配置内存大于123bytes 或内存不足时,转调用一级配置器。
第一级配置器 __malloc_alloc_template
class__malloc_alloc_template {
private:
//以下都是函式指标,所代表的函式将用来处理内存不足的情况。
//oom : out of memory.
staticvoid *oom_malloc(size_t);
staticvoid *oom_realloc(void*, size_t);
staticvoid (* __malloc_alloc_oom_handler)();//内存不足处理例程,被上面的两个函数调用
public:
static void * allocate(size_t n)
{
void *result=malloc(n);//第一级配置器直接使用 malloc()
//以下,无法满足需求时,改用 oom_malloc()
if (0== result) result= oom_malloc(n);
return result;
}
staticvoid deallocate(void*p, size_t /* n */)
{
free(p); //第一级配置器直接使用free()
}
staticvoid * reallocate(void*p, size_t /* old_sz */,size_t new_sz)
{
void * result =realloc(p, new_sz);//第一级配置器直接使用 rea
//以下,无法满足需求时,改用 oom_realloc()
if (0== result) result= oom_realloc(p, new_sz);
return result;
}
//以下模拟 C++的 set_new_handler(). 换句话说,你可以透过它,
//指定你自己的 out-of-memory handler
staticvoid (* set_malloc_handler(void (*f)()))()
{
void (* old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler =f;
return(old);
}
};//CLASS定义结束
//malloc_alloc out-of-memory handling
//初值为 0。有待客端设定。
template<int inst>
void (*__malloc_alloc_template<inst>::__malloc_alloc_oom_handler)()= 0;
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;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();//呼叫处理例程,企图释放内存。
result=malloc(n); //再次尝试配置内存。
if (result) return(result);
}
}
template<int inst>
void*__malloc_alloc_template<inst>::oom_realloc(void*p, size_t n)
{
void (* my_malloc_handler)();
void *result;
for(;;) { //不断尝试释放、配置、再释放、再配置…
my_malloc_handler =__malloc_alloc_oom_handler;
if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }
(*my_malloc_handler)();//呼叫处理例程,企图释放内存。
result= realloc(p, n);//再次尝试配置内存。
if (result) return(result);
}
}
//注意,以下直接将参数 inst指定为 0。
typedef__malloc_alloc_template<0> malloc_alloc;
第二级配置器 __default_alloc_template
enum {_ALIGN = 8};//小型区块的上调边界
enum {_MAX_BYTES = 128};//小型区块的上限
enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN,free-list的个数
template <bool threads, int inst>
class __default_alloc_template
{
private:
/*将__bytes上调至8的倍数*/
static size_t ROUND_UP(size_t bytes) {
return (((bytes) + _ALIGN-1) & ~(_ALIGN - 1));
}
//free-list的节点构造
union obj {
union obj* free_list_link;
char client_data[1]; /* The client sees this.*/
};
private:
static obj* volatile free_list[__NFREELISTS];
//根据区块大小,决定使用哪个free-list
static size_t FREELIST_INDEX(size_t bytes) {
return (((bytes) + _ALIGN-1)/_ALIGN - 1);
}
static void* refill(size_t n);
static char* chunk_alloc(size_t size, int& nobjs);
// Chunk allocation state.
static char* start_free;//内存池起始位置
static char* end_free;//内存池结束位置
static size_t heap_size;
public:
/* n must be > 0 */
static void* allocate(size_t n)//申请空间
{...}
/* p may not be 0 */
static void deallocate(void* p, size_t n)//释放空间
{...}
//重新配置空间
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 = 0;
template <bool threads, int inst>
char* __default_alloc_template<threads, inst>::_end_free = 0;
template <bool threads, int inst>
size_t __default_alloc_template<threads, inst>::_heap_size = 0;
template <bool threads, int inst>
typename __default_alloc_template<threads, inst>::obj* volatile
__default_alloc_template<threads, inst> ::free_list[_NFREELISTS] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
参见书记 p61或者
参考链接