• 欢迎浏览“String me = Creater\忠实的资深Linux玩家;”,请文明浏览,理性发言,有侵犯你的权益请邮件我(creater@vip.qq.com).
  • 把任何的失败都当作一次尝试,不要自卑;把所有的成功都想成是一种幸运,不要自傲。
  •    5年前 (2013-04-25)  STL |   10 条评论  12 
    文章评分 0 次,平均分 0.0

    当申请的内存比较小时,频繁的申请与释放很容易造成碎片,而且还会造成配置的负担。所以当小额分配时,在内存池中进行分配,这样就避免了申请和释放带来的碎片,还避免了频繁申请带来的效率问题。
    STL的第二级空间配置器的做法是:如果申请的内存大于128字节,则交给第一级,否则在第二级中用内存池管理。基本原理是,每次配置一大块内存,并用自由链表进行维护,内存的申请直接在自由链表中划拨。释放的内存则由自由链表回收。

    对于小额区块内存,都会上升到8的倍数,比如13会上升到16.31会上升到32.
    第二级配置器维护16个自由链表,分别管理大小为『8,16,24.。。』的区块。以下3个分别为小额内存的上升边界,小额内存的上限,自由链表的个数。
    enum {__ALIGN = 8};
    enum {__MAX_BYTES = 128};
    enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
    看下面的代码:

    template
    class __default_alloc_template {
    
    private:
    # ifndef __SUNPRO_CC
        enum {__ALIGN = 8};
        enum {__MAX_BYTES = 128};
        enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
    # endif
    	//这个函数用于获取上升至8的倍数后的大小
      static size_t ROUND_UP(size_t bytes) {
            return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
      }
    __PRIVATE:
     //自由链表结构,为什么这么设计,后面说
      union obj {
            union obj * free_list_link;
            char client_data[1];    /* The client sees this.        */
      };
    private:
    # ifdef __SUNPRO_CC
        static obj * __VOLATILE free_list[];
            // Specifying a size results in duplicate def for 4.1
    # else
    //存储各个小额内存地址的自由链表
        static obj * __VOLATILE free_list[__NFREELISTS];
    # endif
     //返回上边自由链表的索引
      static  size_t FREELIST_INDEX(size_t bytes) {
            return (((bytes) + __ALIGN-1)/__ALIGN - 1);
      }
    
      // Returns an object of size n, and optionally adds to size n free list.
    	// 返回n字节,并自动增加到大小为n的自由链表中
      static void *refill(size_t n);
      // Allocates a chunk for nobjs of size "size".  nobjs may be reduced
      // if it is inconvenient to allocate the requested number.
    	// 返回nobjs个size大小的内存块,实际申请的size大小的个数靠nobjs这个值-结果参数返回
      static char *chunk_alloc(size_t size, int &nobjs);
    
      // Chunk allocation state.
      static char *start_free;
      static char *end_free;
      static size_t heap_size;
    
    # ifdef __STL_SGI_THREADS
        static volatile unsigned long __node_allocator_lock;
        static void __lock(volatile unsigned long *);
        static inline void __unlock(volatile unsigned long *);
    # endif
    
    # ifdef __STL_PTHREADS
        static pthread_mutex_t __node_allocator_lock;
    # endif
    
    # ifdef __STL_WIN32THREADS
        static CRITICAL_SECTION __node_allocator_lock;
        static bool __node_allocator_lock_initialized;
    
      public:
        __default_alloc_template() {
    	// This assumes the first constructor is called before threads
    	// are started.
            if (!__node_allocator_lock_initialized) {
                InitializeCriticalSection(&__node_allocator_lock);
                __node_allocator_lock_initialized = true;
            }
        }
      private:
    # endif
    
        class lock {
            public:
                lock() { __NODE_ALLOCATOR_LOCK; }
                ~lock() { __NODE_ALLOCATOR_UNLOCK; }
        };
        friend class lock;
    
    public:
    
      /* n must be > 0      */
      static void * allocate(size_t n)
      {
        obj * __VOLATILE * my_free_list;
        obj * __RESTRICT result;
    
        if (n > (size_t) __MAX_BYTES) {
            return(malloc_alloc::allocate(n));
        }
        my_free_list = free_list + FREELIST_INDEX(n);
        // Acquire the lock here with a constructor call.
        // This ensures that it is released in exit or during stack
        // unwinding.
    #       ifndef _NOTHREADS
            /*REFERENCED*/
            lock lock_instance;
    #       endif
        result = *my_free_list;
        if (result == 0) {
            void *r = refill(ROUND_UP(n));
            return r;
        }
        *my_free_list = result -> free_list_link;
        return (result);
      };
    
      /* p may not be 0 */
      static void deallocate(void *p, size_t n)
      {
        obj *q = (obj *)p;
        obj * __VOLATILE * my_free_list;
    
        if (n > (size_t) __MAX_BYTES) {
            malloc_alloc::deallocate(p, n);
            return;
        }
        my_free_list = free_list + FREELIST_INDEX(n);
        // acquire lock
    #       ifndef _NOTHREADS
            /*REFERENCED*/
            lock lock_instance;
    #       endif /* _NOTHREADS */
        q -> free_list_link = *my_free_list;
        *my_free_list = q;
        // lock is released here
      }
      static void * reallocate(void *p, size_t old_sz, size_t new_sz);
    } ;
    
     

    除特别注明外,本站所有文章均为String me = "Creater\忠实的资深Linux玩家";原创,转载请注明出处来自http://unix8.net/home.php/864.html

    关于

    发表评论

    暂无评论

    切换注册

    登录

    忘记密码 ?

    切换登录

    注册

    扫一扫二维码分享