SGI STL 第二级空间配置器 内存池

从内存池中取控件给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。找到一块就返回给用户,找不到就调用第一级配置器。

你可能感兴趣的:(C++,STL)