STL空间配置的标准接口:
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference_type
//一个嵌套的class template.class rebind<U>拥有唯一成员other,那allocator::allocator()
allocator::rebind
//default constructor
allocator::allocator()
//copy constructor
allocator::allocator(const allocator &)
//泛化的copy constructor
template<class U>
allocator::allocator(const allocator<U> &)
//destructor
allocator::~allocator()
//返回某个对象的地址。算式a.address(x)等同于&x
pointer allocator::address(reference x) const
//返回某个const对象的地址。算式a.address(x)等同于&x
const_pointer allocator::address(const_referenc x) const
//配置空间,足以存储n个T对象。第二参数是个提示。实现上可能会利用它来增进区域性,或完全忽略之。
pointer allocator::allocate(size_type n ,const void * = 0 )
//归还先前配置的空间
void allocator::deallocate(pointer p ,size_type n)
//返回可成功配置的最大量
size_type allocator::max_size() const
//等同于new((void *)p) T(x)
void allocator::construct(pointer p ,const T& x)
//等同于p->~T()
void allocator::destory(pointer p)
SGI设计了双层级配置器,第一级配置器直接使用malloc()和free(),第二级配置器则视情况采用不同的策略:当配置区块超过128bytes时,视之为“足够大”,便调用第一级配置器;当配置区小于128bytes时,视之为“过小”,为了降低额外负担,便采用复杂的memory pool 整理方式,而不再求助于第一级配置器。整个设计究竟只开放第一级配置器,取决于_USE_MALLOC是否被定义:
#ifdef __USE_MALLOC
...
typedef __malloc_alloc_template<0> malloc_alloc ;
typedef malloc_alloc alloc ; //令alloc为第一级配置器
#else
//令alloc为第二级配置器
typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS,0> alloc ;
#endif /*! __USE_MALLOC*/
SGI STL 第一级配置器 template<int inst> class __malloc_alloc_template {…} ; 其中: 1. allocate()直接使用malloc(),deallocate()直接使用free()。 2. 模拟C++的set_new_handler()以处理内存不足的状况。 |
第一级配置器以malloc(),free(),realloc()等C函数执行实际的内存配置、释放、重配置操作。
SGI STL 第二级配置器 template<bool threads,int inst> class __default_alloc_template {…} ; 其中: 1. 维护16个自由链表(free lists),负责16种小型区块的次配置能力。 内存池(memory pool)以malloc()配置而得。如果内存不足,转调用第一级配置器。 2. 如果需求区块大于128byte,就转调用第一级配置器。 |
SGI第二级配置器的做法是,如果区块够大,超过128bytes时,就移交第一级配置器处理。当区块小于128bytes时,则以内存池(memorypool)管理,此法又称为次层配置(sub-allocation):每次配置一大块内存,并维护对应之自由链表(free-list)。下次若再有相同大小的内存需求,就直接从free-list中拨出。如果客户端释还小额区块,就由配置器回收到free-list中------是的,别忘了,配置器除了负责配置,也负责回收。为了方便管理,SGI第二级配置器会主动将任何小额区块的内存需求量上调至8的倍数(例如客户端要求30bytes,就自动调整为32bytes),并维护16个free-lists,各自管理大小分别为8,16,24,32,40,48,56,64,72,80,88,96,104,112,128bytes的小额区块。Free-lists的节点结构如下:
union obj{
union obj *free_list_link ; //没有分配出去时,视为一个指针,指向相同形式的另一个obj。
char client_data[1] ; /*被分配出去时,指向实际区块。*/
}