从内存池中取控件给free list 使用,是chunk_alloc的工作:
template <bool __threads, int __inst>
char*
__default_alloc_template<__threads, __inst>::
chunk_alloc(size_t __size, int& __nobjs)//待分配块的数量是引用
{
char* __result;
size_t __total_bytes = __size * __nobjs;//需要分配的空间
size_t __bytes_left = _S_end_free - _S_start_free; //剩余的空间
//如果剩余空间大于需求空间
if (__bytes_left >= __total_bytes) {
__result = _S_start_free; //分配空间地址给__result
_S_start_free += __total_bytes;//调整_S_start_free指针
return(__result); //将分配的空间返回给用户
//如果剩余空间大于一个size空间小于整个待分配的空间
} else if (__bytes_left >= __size) {
//将仅剩下的的空间分配给用户即left/size个块
__nobjs = (int)(__bytes_left/__size);//修改块的数量
__total_bytes = __size * __nobjs;
__result = _S_start_free;
_S_start_free += __total_bytes; //调整_S_start_free指针
return(__result); //返回给用户
//如果内存池中没有内存了
} else {
//调整分配空间量为待分配量的两倍
size_t __bytes_to_get =
2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
// Try to make use of the left-over piece.
//首先将内存池中剩余的空间编入free list中
if (__bytes_left > 0) {
//寻找剩余空间编入的位置
_Obj* __STL_VOLATILE* __my_free_list = //二级指针
_S_free_list + _S_freelist_index(__bytes_left);
//在该位置处进行插入链接
((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
*__my_free_list = (_Obj*)_S_start_free;
}
//使用malloc函数直接进行请求空间
_S_start_free = (char*)malloc(__bytes_to_get); //分配需求的空间
//如果malloc分配失败,则向其他free list进行补充
if (0 == _S_start_free) {
size_t __i;
_Obj* __STL_VOLATILE* __my_free_list;
_Obj* __p;
// Try to make do with what we have. That can't
// hurt. We do not try smaller requests, since that tends
// to result in disaster on multi-process machines.
//挨个的free list查找
for (__i = __size;__i <= (size_t) _MAX_BYTES;
__i += (size_t) _ALIGN) {
__my_free_list = _S_free_list + _S_freelist_index(__i);
__p = *__my_free_list;
if (0 != __p) {//成功,则进行分配到内存池中
*__my_free_list = __p -> _M_free_list_link;
_S_start_free = (char*)__p;
_S_end_free = _S_start_free + __i;
return(_S_chunk_alloc(__size, __nobjs));//函数在进行分配
// Any leftover piece will eventually make it to the
// right free list.
}
}
//如果内存不足
_S_end_free = 0; // In case of exception.
//调用一级空间配置器进行分配内存,如果没有获得内存,将会抛出异常
_S_start_free =(char*)malloc_alloc::allocate(__bytes_to_get);
// This should either throw an
// exception or remedy the situation. Thus we assume it
// succeeded.
}
//如果成功获取内存
_S_heap_size += __bytes_to_get;//内存池的总量
_S_end_free = _S_start_free + __bytes_to_get;//内存池的尾部指针
return(_S_chunk_alloc(__size, __nobjs)); //递归调用
}
}
上述的chunk_alloc函数以 _S _end _free - _S _start _free来判断内存池中是否有可用的空间。
如果空间量充足,就直接分配20个区块给free _list.
如果不足以提供20个区块,但是还足够供应一个以上的区块,就拨出这不足20个区块的空间出去。这时,nobjs参数将会修改为实际能够供应的区块数;
如果内存池连一个区块空间都无法供应,此时需要利用malloc从heap中配置内存,为内存池注入一定量的空间以应付需求。这个量为需求量的两倍空间。
如果heap空间也分配不出内存时,chunk_alloc寻找“尚未使用且区块足够大“的free lists。找到一块就返回给用户,找不到就调用第一级配置器。