zoukankan      html  css  js  c++  java
  • STL初探——__default_alloc_template内存池

      _S_chunk_alloc() 函数负责从内存池取出空间给free-list,如果内存池内存充足,则直接拿出足够的内存块给自由链表,如果内存不够所有需求但是对一小块需求能满足,则拿出一小块内存给自由链表并返回,如果一点儿内存也没有,则进行遍历压榨,最终如果真的没有,就只能求助于第一级配置器。代码如下:

    template <bool __threads, int __inst>
    char*
    __default_alloc_template<__threads, __inst>::_S_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;
            _S_start_free += __total_bytes;
            return(__result);
        } 
        else if (__bytes_left >= __size)                     //满足至少一个区块的需求
        {
            __nobjs = (int)(__bytes_left/__size);
            __total_bytes = __size * __nobjs;
            __result = _S_start_free;
            _S_start_free += __total_bytes;
            return(__result);
        } 
        else                                                //完全不满足需求
        {
            size_t __bytes_to_get = 
                2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
                                                            //利用剩下的一点点零头.
            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;
            }
            _S_start_free = (char*)malloc(__bytes_to_get);
            if (0 == _S_start_free) 
            {
                size_t __i;
                _Obj* __STL_VOLATILE* __my_free_list;
                _Obj* __p;
                //看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));                //反复压榨内存
                    }
                }
                //执行到了这一步,说明没内存了,_S_end_free初始化置于零,并调用第一级配置器配置内存重新设定_S_start_free。
                _S_end_free = 0;    
                _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
            }
            _S_heap_size += __bytes_to_get;
            _S_end_free = _S_start_free + __bytes_to_get;
            //
            return(_S_chunk_alloc(__size, __nobjs));
        }
    }

      为了好懂,我们这样想,假设程序开始运行,客端就开始调用_S_chunk_alloc(32,20)函数,假设 malloc() 一次性配置40个32bytes的内存区块,其中20个作为函数返回值,之后1个被交给客户端,剩下19个交给 free-list[3] 维护,要的时候再去取即可。另外20个留给内存池。接下来客端调用_S_chunk_alloc(64,20),64个是归 free-list[7] 维护的,然而 free-list[7] 空空如也,必须向内存池寻求支持,内存池能够供应 20 x 32 / 64 = 10个区块,就把这10个区块返回,其中1个交给客户端,剩下九个交给 free-list[7] 维护,内存池空了,假设接下来再调用 _S_chunk_alloc(96,20) ,64个是归 free-list[11] 维护的,然而 free-list[11] 空空如也,必须向内存池寻求帮助,而内存池也是空的,于是又开始调用 malloc() 分配 20 +n 个 96大小的内存块,其中20内存块返回,一个被交付,剩下19个交给 free-list[11] 维护,而还有n个 96 大小的内存块就交给内存池维护...... 

      如果最终内存里面的堆区没有内存了,无法为内存池注入新的内存,malloc() 行动失败,_S_chunk_alloc()就在free-list里寻找有没有 “尚未应用区块,且区块足够大”,找到就挖出一块并交出,找不到就调用第一级配置器,第一级配置器其实也是用 malloc() 来配置内存,但它有 out-of-memory 处理机制(类似new handler),或许有机会释放其他的内存并拿来此处使用,如果可以就内存配置成功,否则就抛出 bad_alloc()异常。

     

    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    js高级1
    JUC总览
    7 种阻塞队列相关整理
    Exchanger 相关整理
    Semaphore 相关整理
    ConcurrentLinkedQueue 相关整理
    ConcurrentHashMap(1.8) 相关整理
    ConcurrentHashMap(1.7) 相关整理
    ReentrantReadWriteLock 相关整理
    LockSupport 工具相关整理
  • 原文地址:https://www.cnblogs.com/Forever-Road/p/6811722.html
Copyright © 2011-2022 走看看