您的位置:首页 > 其它

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

2013-10-04 23:22 531 查看
作用:帮助容器配置空间存放信息

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: