剖析SGI STL空间配置器(_S_refill内存块填充函数)
通过allocate函数申请内存块时,会在对应自由链表下取内存块,当该位置下没有内存块链时,就需要调用_S_refill,填充该位置下的内存块,比如刚开始时,每个自由链表_S_free_list的结点都为nullptr,就需要填充内存块。
_S_refill的函数定义如下:
template <bool __threads, int __inst>
void* __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
{
int __nobjs = 20;
char* __chunk = _S_chunk_alloc(__n, __nobjs);
_Obj* __STL_VOLATILE* __my_free_list;
_Obj* __result;
_Obj* __current_obj;
_Obj* __next_obj;
int __i;
if (1 == __nobjs) return(__chunk);
__my_free_list = _S_free_list + _S_freelist_index(__n);
/* Build free list in chunk */
__result = (_Obj*)__chunk;
*__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
for (__i = 1; ; __i++) {
__current_obj = __next_obj;
__next_obj = (_Obj*)((char*)__next_obj + __n);
if (__nobjs - 1 == __i) {
__current_obj -> _M_free_list_link = 0;
break;
} else {
__current_obj -> _M_free_list_link = __next_obj;
}
}
return(__result);
}
参数__n是要填充chunk块的大小,要填充chunk块,内存来源就需要继续向下申请了,char* __chunk = _S_chunk_alloc(__n, __nobjs);
的功能就是。__chunk是返回的内存块首地址,__nobjs以引用的形式传进_S_chunk_alloc,_S_chunk_alloc执行结束__nobjs的值就是申请的__n大小的chunk块的块数了。
申请完成后,_S_refill函数还需要把申请到的chunk块串起来。
举个例子,参数__n为8,通过_S_chunk_alloc申请到了5块的内存,也就是40字节,后面的过程可以用下面这张图来简单概括:
最后把申请到的第一个chunk块返回给allocate函数使用,然后再把剩余的chunk块串到对应的自由链表结点下。