stl_alloc.h

sgi stl的allocate由2級配置器組成, 默認爲第二級, 第二級配置器分配內存的時候, 首先查看需要分配的內存塊大小,如果大於160, 調用第一級配置器, 否則用內存池來分配內存。 這樣對小塊內存的分配效率高,不容易產生內存碎片。
一級配置器:
template <int __inst>
class __malloc_alloc_template {
二級配置器
template <bool threads, int inst>
class __default_alloc_template {

sgi stl有自己的配置器實現, 缺省的時候不使用標準配置器。
以vector爲例:
vector的定義:
template <class _Tp, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Tp) >
class vector : protected _Vector_base<_Tp, _Alloc>
這裏__STL_DEFAULT_ALLOCATOR是這樣的一個東西:
見stl_config.h
# ifndef __STL_DEFAULT_ALLOCATOR
#   ifdef __STL_USE_STD_ALLOCATORS
#     define __STL_DEFAULT_ALLOCATOR(T) allocator< T >
#   else
#     define __STL_DEFAULT_ALLOCATOR(T) alloc
#   endif
# endif
如果定義了__STL_USE_STD_ALLOCATORS, 那麼__STL_DEFAULT_ALLOCATOR 爲 allocator<T>, 這個時候是標準配置器, 我們可以用自定義的allocator, 否則__STL_USE_STD_ALLOCATORS爲alloc, alloc是sgi stl的一個配置器實現,這個時候即使我們傳入自己的配置器, 也會被忽略.

最後還有一個template<class _Tp, class _Allocator>
struct _Alloc_traits {} 並且根據不同的配置器作了特化。只有在定義了__STL_USE_STD_ALLOCATORS的時候, 纔會定義這個類。
在各個容器中,使用_Alloc_traits來萃取當前使用的allocator的實際類型。
如vector:
_Vector_base用來分配和釋放內存, 並且封裝了標準配置器和sgi配置器的不同。
當沒有定義__STL_USE_STD_ALLOCATORS, 則使用的是alloc, 不需要_Alloc_traits. 此時就是確定使用alloc來分配, 不需要萃取類型信息。
_Vector_base
template <class _Tp, class _Alloc>
class _Vector_base {
public:
  typedef _Alloc allocator_type;
  allocator_type get_allocator() const { return allocator_type(); }

  _Vector_base(const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) {}
  _Vector_base(size_t __n, const _Alloc&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0)
  {
    _M_start = _M_allocate(__n);
    _M_finish = _M_start;
    _M_end_of_storage = _M_start + __n;
  }

  ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }

protected:
  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;

  typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;
  _Tp* _M_allocate(size_t __n)
    { return _M_data_allocator::allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n)
    { _M_data_allocator::deallocate(__p, __n); }
};

如果定義了__STL_USE_STD_ALLOCATORS
template <class _Tp, class _Allocator, bool _IsStatic>
class _Vector_alloc_base {
public:
  typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
          allocator_type;
  allocator_type get_allocator() const { return _M_data_allocator; }

  _Vector_alloc_base(const allocator_type& __a)
    : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) 
  {}
  
protected:
  allocator_type _M_data_allocator;
  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;

  _Tp* _M_allocate(size_t __n)
    { return _M_data_allocator.allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n)
    { if (__p) _M_data_allocator.deallocate(__p, __n); }
};

// Specialization for allocators that have the property that we don't
// actually have to store an allocator object.  
template <class _Tp, class _Allocator>
class _Vector_alloc_base<_Tp, _Allocator, true> {
public:
  typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
          allocator_type;
  allocator_type get_allocator() const { return allocator_type(); }

  _Vector_alloc_base(const allocator_type&)
    : _M_start(0), _M_finish(0), _M_end_of_storage(0) 
  {}
  
protected:
  _Tp* _M_start;
  _Tp* _M_finish;
  _Tp* _M_end_of_storage;

  typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type;
  _Tp* _M_allocate(size_t __n)
    { return _Alloc_type::allocate(__n); }
  void _M_deallocate(_Tp* __p, size_t __n)
    { _Alloc_type::deallocate(__p, __n);}
};

template <class _Tp, class _Alloc>
struct _Vector_base
  : public _Vector_alloc_base<_Tp, _Alloc,
                              _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
{
  typedef _Vector_alloc_base<_Tp, _Alloc, 
                             _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
          _Base;
  typedef typename _Base::allocator_type allocator_type;

  _Vector_base(const allocator_type& __a) : _Base(__a) {}
  _Vector_base(size_t __n, const allocator_type& __a) : _Base(__a) {
    _M_start = _M_allocate(__n);
    _M_finish = _M_start;
    _M_end_of_storage = _M_start + __n;
  }

  ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
};    

_Vector_base從_Vector_alloc_base<_Tp, _Alloc,
                              _Alloc_traits<_Tp, _Alloc>::_S_instanceless>派生。
如果傳入vector的模辦參數_Alloc的類型爲allocate<_Tp1>, 這是stl_alloc.h裏定義的一個配置器, 封裝了alloc, 實際分配刪除都調用alloc進行。 根據_Alloc_traits的特化, _S_instanceless爲true,  而如果_Alloc爲自定義配置器,_S_instanceless爲false. 當_S_instanceless爲true, 則會使用_Alloc_traits<_Tp, _Allocator>::_Alloc_type作爲真正的配置器。typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; 
_S_instanceless爲false, 則使用_Alloc_traits<_Tp, _Allocator>::allocator_type。 這兩個類型在_Alloc_traits中都有定義, 最後,根據配置器的特點, vector用萃取出的合適的配置器分配內存。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章