1. 程式人生 > >STL初探——第二級配置器 __default_alloc_template的學習心得

STL初探——第二級配置器 __default_alloc_template的學習心得

空間配置 def 管理 使用 函數 效率 需求 typename []

  SGI STL 第二級配置器使用的是memory pool,即內存池,相比較於第一級空間配置器,第二級空間配置器多了許多限制,主要是為了防止申請小額區塊過多而造成內存碎片。當然小額區塊在配置時實際上是對空間配置器效率的一種傷害。另外,索求任何一塊內存,都得需要一些額外內存來進行標記,雖然這些標記占內存很小很小,但螞蟻多咬死象,小區塊多了,這些小標記還是挺浪費內存的,但這也無法避免,畢竟系統需要靠這些小標記管理內存。

  SGI 第二級配置器的做法是,如果區塊足夠大,超過128bytes時,就移交第一級配置器處理。當區塊小於128bytes時,則以內存池的方式管理,第二級配置器也叫做次層配置器:每次配置一大塊內存,並維護對應的自由鏈表:free-list。為了方便管理,SGI STL 第二級配置器會主動為小額區塊的需求量的大小上調至 8 的倍數,並維護16個 free-list,依次為8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,free-list節點結構如下:

  union _Obj {
        union _Obj* _M_free_list_link;
        char _M_client_data[1];    /* The client sees this.        */
  };

  _Obj 用的是 union,_M_free_list_link,是一個指針,指向下一個 _Obj,_M_client_data 也可以當做一個指針,指向實際區塊,這樣做的好處是不會為了維護鏈表所必須的指針而造成內存的另一種浪費。

  技術分享

  

template <bool threads, int inst>
class
__default_alloc_template { private: //區塊上調枚舉 #if ! (defined(__SUNPRO_CC) || defined(__GNUC__)) enum {_ALIGN = 8}; enum {_MAX_BYTES = 128}; enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN # endif //區塊上調函數 static size_t _S_round_up(size_t __bytes) { return (((__bytes) + (size_t) _ALIGN-1
) & ~((size_t) _ALIGN - 1)); } __PRIVATE: //鏈表節點聯合體 union _Obj { union _Obj* _M_free_list_link; char _M_client_data[1]; /* The client sees this. */ }; private: # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC) static _Obj* __STL_VOLATILE _S_free_list[]; # else //16個 free-list static _Obj* __STL_VOLATILE _S_free_list[_NFREELISTS]; # endif static size_t _S_freelist_index(size_t __bytes) { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); } static void* _S_refill(size_t __n); static char* _S_chunk_alloc(size_t __size, int& __nobjs); static char* _S_start_free; //內存池起始 static char* _S_end_free; //內存池結束 static size_t _S_heap_size; //區塊數 public: /* __n must be > 0 */ static void* allocate(size_t __n) { ... }; /* __p may not be 0 */ static void deallocate(void* __p, size_t __n) { ... } static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz); }; //這四個函數是靜態數據成員的定義與初始設定 //__threads是線程設定,咱們不管,__inst完全沒用到。。。 template <bool __threads, int __inst> char* __default_alloc_template<__threads, __inst>::_S_start_free = 0; template <bool __threads, int __inst> char* __default_alloc_template<__threads, __inst>::_S_end_free = 0; template <bool __threads, int __inst> size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0; template <bool __threads, int __inst> typename __default_alloc_template<__threads, __inst>::_Obj* __STL_VOLATILE __default_alloc_template<__threads, __inst> ::_S_free_list[ # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC) _NFREELISTS # else __default_alloc_template<__threads, __inst>::_NFREELISTS # endif ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; };

STL初探——第二級配置器 __default_alloc_template的學習心得