剖析SGI STL空间配置器(deallocate内存回收函数和reallocate内存扩充函数)
deallocate内存回收函数
deallocate函数的定义:
static void deallocate(void* __p, size_t __n)
{
if (__n > (size_t) _MAX_BYTES)
malloc_alloc::deallocate(__p, __n);
else {
_Obj* __STL_VOLATILE* __my_free_list
= _S_free_list + _S_freelist_index(__n);
_Obj* __q = (_Obj*)__p;
// acquire lock
# ifndef _NOTHREADS
/*REFERENCED*/
_Lock __lock_instance;
# endif /* _NOTHREADS */
__q -> _M_free_list_link = *__my_free_list;
*__my_free_list = __q;
// lock is released here
}
}
deallocate函数需要接收两个参数:一个是回收内存的起始地址,另一个是回收内存的大小。
如果回收内存的大小大于128字节,调用的是malloc_alloc::deallocate(__p, __n);
,该函数所做的工作就只有free一个动作:
如果释放的内存小于128字节,只需把这块chunk块以头插的方式,插入对应自由链表_S_free_list的结点即可。在多线程环境下,对自由链表的操作是需要加锁的。
reallocate内存扩充/缩小函数
reallocate函数定义:
template <bool threads, int inst>
void*
__default_alloc_template<threads, inst>::reallocate(void* __p,
size_t __old_sz,
size_t __new_sz)
{
void* __result;
size_t __copy_sz;
if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
return(realloc(__p, __new_sz));
}
if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
__result = allocate(__new_sz);
__copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
memcpy(__result, __p, __copy_sz);
deallocate(__p, __old_sz);
return(__result);
}
如果新内存和旧内存的大小都大于128字节,直接调用库函数里的realloc函数。
如果新内存和旧内存提升后的大小需要的都是同样大小的chunk块,则不需要做任何改变。
否则就是申请一块新内存,比较新旧内存的大小,把小内存的内容往大内存拷,再释放旧内存,把新内存地址返回即可。