现在的位置: 首页 > 综合 > 正文

STL源码剖析_读书笔记:第二章 空间配置器 一级和二级配置器篇

2018年05月18日 ⁄ 综合 ⁄ 共 7562字 ⁄ 字号 评论关闭

作用:帮助容器配置空间存放信息

SGI空间配置器

标准空间配置器allocator:效率不好,只对::operator new::operator delete做一层封装

特殊空间配置器alloc   
:将
new算式分为两阶段:用::operator配置内存,构造对象;

delet算式分为两阶段:析构对象,用::operator delete释放内存

 

特殊空间配置器

内存配置:allocate(),判断区块大小,大于128字节调用一级配置器,小于检查自由链表中若有可用区块直接使用,否则为自由链表重新填充空间

内存释放:deallocate(),判断区块大小,大于128字节调用一级配置器,小于则找到对应自由链表,进行区块回收。

对象构造:construct()

对象析构:destroy()

 

双层配置器

一级配置器:使用malloc(),free()进行内存的分配与释放。类名:__malloc_alloc_template

二级配置器:小于128字节时,采用内存池,维护自由链表,可从自由链表进行内存的分配与释放。内存需求量需上调为8的倍数。类名:__default_alloc_template

 

下面的程序是关于第一级和第二级配置器

#include<iostream>
#include<string>
#include<vector>
#include<iterator>

#include <new.h> //使用placement new
#include <stddef.h> //常用常量
#include <limits.h> //类型最值的常量
//#include <algobase.h>

#include <memory> //STL配置器定义于此
//以下是SGI_STL_空间配置器的头文件
//#include <stl_construct.h> //定义有全域函式
////#include <stl_uninitialized.h> //定义了全局函数,赋值大内存数据

using namespace std;

template<class T>
inline T* allocate(ptrdiff_t size,T* )
{
 set_new_handler(0);
 T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
 if(tmp==0)
 {
  cerr<<"内存分配失败"<<endl;
  exit(1);
 }
 return tmp;
}

template<class T>
inline void deallocate(T* maBlock)
{
 ::operator delete(maBlock);
}

template<typename T>
class MaAllocator
{
public:
 typedef T value_type;
 typedef T* pointer;
 typedef const T* const_pointer;
 typedef T& reference;
 typedef const T& const_reference;
 typedef size_t size_type;
 typedef ptrdiff_t difference_type;

public:
 pointer allocate(size_type n)
 {
  return ::allocate((differenc_type)n,(pointer)0);//::表示在全局域
 }

 void deallocate(pointer p)
 {
  ::deallocate(p);
 }

 pointer address(reference x){return (pointer)&x;}
 const_pointer address(const_reference x){return (const_pointer)&x;}
 size_type init_page_size()
 {
  return max(size_type(1),size_type(4096/sizeof(T)));
 }

 size_type max_size() const
 {
  return max(size_type(1),size_type(UINT_MAX/sizeof(T)));
 }
};

 //特化版本:
template<>
class MaAllocator<void>
{
public:
 typedef void* pointer;
};

 

template<class T1,class T2>
inline void construct(T1* p,const T2& value)//作用:将初值设定到指针所指的空间上
{
 new(p) T(value);//调用T1::T1(value)
}

//销毁函数不返回任何类型
template<typename T>
inline void destroy(T* pointer)//将指针所指之物析构掉
{
 pointer->~T();//调用~T()
}

/*接受两个迭代器,找出元素的数值型别,用_type_traits<>求最适当措施
对迭代器进行析构,由于析构的东西多,必须判定析构函数是否真正有用,用value_type判定
若为true_type,表明T为简单类型,是无用析构函数,则什么都不做*/
template<typename ForwardIter>
inline void destroy(ForwardIter first,ForwardIter last)
{
 _destroy(first,last,value_type(first));//用value_type获取型别
}

//判断元素的数值型别(value_type)是否有trivial destructor(无用的析构函数,即系统自带的)
template<class ForwardIterator,class T>
inline void _destroy(ForwardIterator first,ForwardIterator last,T*)
{
 /*_type_traits<T>这个模板类根据不同的T类型定义不同的has_trivial_destructor,如果T是简单类型
 就定义为_true_type类型,否则定义为_false_type类型。这两个类。*/
 typedef typename _type_traits<T>::has_trivial_destructor trivial_destructor;//?
 destroy_aux(first,last,trivial_destructor());//?
}

//如果元素的数值型别为non-trivial destructor,T不是简单类型为_false_type,为有效析构函数
template<class ForwardIterator,class _false_type>
inline void _destroy_aux(ForwardIterator first,ForwardIterator last,_false_type)
{
 for(;first!=last;first++)
 {
  destroy(&*first);
 }
}

//如果元素的数值型别为trivial destructor,T为简单类型
//template<class ForwardIterator,class _true_type>
//inline void _destroy_aux(ForwardIterator first,ForwardIterator,_true_type)
//{
//}

//是对迭代器为char* ,wchar_t*
inline void destroy(char* ,char* ){}
//inline void destroy(wchar* ,wchar* ){}
inline void destroy(wchar_t*,wchar_t*){}

template<class T,class Alloc>
class simple_alloc
{
public:
 //static T* allocate(size_t n)
 static T* allocate(size_t n)
 {
  return 0==n?0:(T*)Alloc::allocate(n*sizeof(T));
 }

 static T* allocate()
 {
  return (T*)Alloc::allocate(n*sizeof(T));
 }
 
 static void deallocate(T* p,size_t n)
 {
  if(0!=n)
  {
   Alloc::deallocate(p,n*sizeof(T));
  }
 }

 static void deallocate(T* p)
 {
  Alloc::deallocate(p,sizeof(T));
 }
};
template<typename T,typename Alloc = alloc>
class MaVector
{
public:
 typedef T value_type;
protected:
 //专属空间配置器,每次配置一个元素
 typedef simple_alloc<value_type,Alloc> data_allocator;

 void deallocate()
 {
  if(1)//?
  {
   data_allocator::deallocate(start,end_of_storage-start);
  }
 }
};

template<int inst>
class _malloc_alloc_template
{
private:
 //一下都是函数指针,代表的函数处理内存不足情况,oom=out of memory
 //static void* oom(size_t n)//内存分配溢出时的分配
 //static void* oom_malloc(size_t )
 //{
 //}
 ////static void* oom_realloc(void* ,size_t)
 //static void* oom_realloc(void* ,size_t )
 //{
 //}
 ////static void(*__malloc_alloc_oom_handler)//不能有2个下划线
 //static void(*_malloc_alloc_oom_handler())
 //{
 //}

public:
 static void* allocate(size_t n)
 {
  //第一级配置器用malloc分配
  //void* result = oom_malloc(n);
  void* resule = malloc(n);
  if(0==result)//分配溢出时,改用oom_malloc分配
  {
   result = oom_malloc(n);
  }
  return result;
 }

 //static void deallocate()//必须释放指针的内存
 static void deallocate(void* p)
 {
  free(p);//第一级配置器使用free
 }

 static void* reallocate(void* p,size_t old_sz,size_t new_sz)
 {
  //第一级配置器直接使用realloc
  void* result = realloc(p,new_sz);
  if(0==result)
  {
   result = oom_realloc(p,new_sz);
  }
  return result;
 }

 //下面是自定义的内存溢出处理方法
 static void(*set_malloc_alloc_oom_handler(void (*f)()))()//为什么最后还多一个()
 {
  void(*old)() = _malloc_alloc_oom_handler;
  _malloc_alloc_oom_handler = f;
  return(old);
 }

 void* oom_malloc(size_t n)
 {
  void* result;
  void(*my_malloc_handler());//?
  for(;;)//不断释放,配置,在释放,再配置
  {
   my_malloc_hander = _malloc_alloc_oom_handler;
   if(0==my_malloc_handler)
   {
    throw std::bad_alloc;
   }
   (*my_alloc_handler());
   //result = my_alloc_handler;//分配多个字节
   result = malloc(n);
   if(result)
   {
    return result;
   }
  }
 }
 //void* _malloc_alloc_template<inst>::oom_malloc(size_t n)
 //template<int inst>
 //void(*_malloc_alloc_template<inst>::_malloc_alloc_oom_handler)()=0;

 void* oom_realloc(void* p,size_t n)
 {
  void* result;
  void(*_my_malloc_handler());
  for(;;)
  {
   my_malloc_handler = _malloc_alloc_oom_handler;
   if(0==my_malloc_handler)
   {
    throw std::bad_alloc;
   }
   (*my_malloc_handler());//执行处理函数
   result = realloc(p,n);
   if(result)
   {
    return result;
   }
  }
 }
};

typedef _malloc_alloc_template<0> malloc_alloc;

//第二级配置器
union obj//obj可视为指另一个针指向相同形式的obj
{
 union obj* free_list_link;
 char client_data[1];
};

template<bool threads,int inst>
class _default_alloc_template
{
private:
 //ROUND_UP()将比特上调为8的倍数
 static size_t ROUND_UP(
  
  )
}

enum {_ALIGN = 8};//小数据块的上调边界
enum {_MAX_BYTES = 128}; //小型区块的上限
enum {_NFREELISTS = _MAX_BYTES/_ALIGN};//自由链数目

int main(int argc,char *argv[])
{
 cout<<"2.2:具备次配置力的SGL空间配置器"<<endl;
 cout<<"STL Allocator的函数:"<<endl;
 cout<<"内存申请:alloc::allocate()负责"<<endl;
 cout<<"内存释放: alloc::deallocate()负责"<<endl;
 cout<<"对象构造: 全局 ::construct()负责"<<endl;
 cout<<"对象析构:全局 ::destroy()负责"<<endl;

 cout<<"第一回合:SGI特殊的空间配置器"<<endl;
 cout<<"new 运算式含量阶段操作:1调用::operator new 配置内存,2调用构造函数构造对象内容"<<endl;
 cout<<"delete阶段操作: 调用析构函数将对象析构,2调用::operator delete释放内存"<<endl;
 cout<<"placement new 定义:是重载operator new的全局版本,不能够被自定义版本代替,忽略size_t参数,只返还第二个参数"<<endl;
 cout<<"              用法:pi = new(ptr) int;ptr指向内存缓冲器,比new多了一个“(内存地址)”参数placement new(替换符new)返回值是这个被构造对象的地址"<<endl;
 cout<<"              适用:时间要求高;长时间运行;执行垃圾收集器"<<endl;
 cout<<"new:不能被重载。先调用operator new分内存,调用构造函数初始化内存"<<endl;
 cout<<"operator new:实现不同内存分配应重载operator new"<<endl;
 cout<<"placement new:是operator new的一个重载版本。不分配内存,只返回已分配内存指针。不能删除,但需调用析构函数"<<endl;

 cout<<"第二回合:构造和析构基本工具construct与destroy"<<endl;

 cout<<"第四回合:空间的配置与释放: std::alloc"<<endl;
 cout<<"::operator new()内存配置的基本操作是全局函数=malloc"<<endl;
 cout<<"小型区块内存破碎解决方案:设计双层级配置器。第1层用:malloc,free;第二层视情况而定"<<endl;
 cout<<"配置区<128B时,采用内存池。"<<endl;
 //测试配置器是用1级,还是1,2级同时开启
//#ifdef _USE_MALLOC
// typedef _malloc_alloc_template<0> malloc_alloc;
// typedef malloc_alloc alloc;//令alloc为第一级配置器
//#else
// //另alloc为第二级配置器
// typedef _default_alloc_template<_NODE_ALLOCATOR_THREADS,0> alloc;
//#endif
 cout<<"第5回合:第一级配置器__malloc_alloc_template"<<endl;
 cout<<"new-handler机制:系统内存配置无法满足时,调用你指定的函数,然后抛bad_alloc异常"<<endl;
 cout<<"SGI以malloc而非::operator new 来配置内存"<<endl;

 cout<<"第二级配置器:__default_alloc_template"<<endl;
 cout<<"次层配置:区块小于128bytes,以内存池管理。"<<endl;

 getchar();
 return 0;
}

 

抱歉!评论已关闭.