SGI空间配置器

来源:互联网 发布:安卓编程用什么软件 编辑:程序博客网 时间:2024/05/22 06:40

STL allocater 决定两阶段操作区分开来。内存配置操作由 alloc:allocate()负责,内存操作由alloc:deallocate()负责,对象构造操作由::construct()负责,对象析构操作由::destory()负责。

#include<stl_alloc.h>//包含内存空间的配置和释放#include<stl_construct.h>// 负责 对象内容的构造和析构

这里写图片描述

构造和析构基本工具:construct()和destroy()

#include <new.h> //要想使用 palcement new 能够在一段内存空间构造对象。template <class _T1, class _T2> inline void _Construct(_T1* __p, const _T2& __value) {   new ((void*) __p) _T1(__value); //将value设定到地址p指向的内存上}/***这叫placenew,在指针p所指向的内存空间创建一个类型为T1的对象。调用的构造函数接受一个类型为const   T2&(或其他兼容类型)的参数new   placement 你可以简单的理解为C中的realloc,就是在已有空间的基础上,重新分配一个空间,可以不破坏原来数据,也可以把数据全部用新值覆盖 ****///new一段p指向的内存template <class _T1>inline void _Construct(_T1* __p) {  new ((void*) __p) _T1(); }//以下是destory()第一个版本接受一个指针 调用析构函数 将p所指向的空间析构掉。template <class _Tp>inline void _Destroy(_Tp* __pointer) {  __pointer->~_Tp();  }//以下是destory()第二版本接受两个迭代器此函数设法找出 元素的数值型别,进而利用__type_traits//求取最合适的措施析构对象。template <class _ForwardIterator>inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) {  __destroy(__first, __last, __VALUE_TYPE(__first));}//判断元素类型 是否有trivial destructor 有就是 true_type,没有就是false_typetemplate <class _ForwardIterator, class _Tp>inline void __destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*){  typedef typename __type_traits<_Tp>::has_trivial_destructor          _Trivial_destructor;  __destroy_aux(__first, __last, _Trivial_destructor());}//如果是 non-trivial destructor 则调用destory第一个版本template <class _ForwardIterator>void__destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type){  for ( ; __first != __last; ++__first)    destroy(&*__first);}template <class _ForwardIterator> inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {}----------------------------------------------------------------------/*如果用户不定义析构函数,而是用系统自带的,则说明,析构函数基本没有什么用(但默认会被调用)我们称之为trivial destructor。反之,如果特定定义了析构函数,则说明需要在释放空间之前做一些事情,则这个析构函数称为non-trivial destructor。如果某个类中只有基本类型的话是没有必要调用析构函数的,delelte p的时候基本不会产生析构代码。在STL中空间配置时候destory()函数会判断要释放的迭代器的指向的对象有没有 trivial destructor(STL中有一个 has_trivial_destructor函数,很容易实现检测)放,如果有trivial destructor则什么都不做,如果没有即需要执行一些操作,则执行真正的destory函数。destory()有两个版本,第一个版本接受一个指针,准备将该指针所指之物析构掉,第二个版本接受first和last两个迭代器,准备将[first,last]范围内的所有对象析构掉。我们不知道这个范围有多大,万一很大,而每个对象的析构函数都无关痛痒,那么一次次调用这些析构函数,对效率是一种伤害,因此这里首先利用value_type()获得迭代器所指对象的类别,再利用_type_traits<T>判断该型别的析构函数是否无关痛痒,若是(_true_type),则什么也不做就结束,若否(_false_type),这才以循环的方式巡访整个范围,并在循环中每经历一个对象就调用第一个版本的destory()。**/---------------------------------------------------------------------//以下是destory第二个版本的特化版。inline void _Destroy(char*, char*) {}inline void _Destroy(int*, int*) {}inline void _Destroy(long*, long*) {}inline void _Destroy(float*, float*) {}inline void _Destroy(double*, double*) {}#ifdef __STL_HAS_WCHAR_Tinline void _Destroy(wchar_t*, wchar_t*) {}#endif /* __STL_HAS_WCHAR_T */// --------------------------------------------------// Old names from the HP STL.__STL_END_NAMESPACE

空间的配置和释放。std::alloc

对象构造前的空间配置和对象构造后的空间释放,由

其设计如下:

(1)向system heap要求空间

(2)考虑多线程状态

(3)考虑内存不足的应变措施

(4)考虑过多小型区块的内存碎片问题

考虑到SGI设计了双层配置器,第一层配置器直接使用malloc()和free(),第二层配置器则视情况超过128bytes 则调用第一级配置器;小于128bytes 便采用复杂的 内存池 整理方式。

第一级配置器 _ _malloc_alloc_template 剖析

// 以下是第一級配置器。// 注意,無「template型別參數」。「非型別參數」inst完全沒派上用場。template <int inst>class __malloc_alloc_template {private:static void *oom_malloc(size_t);static void *oom_realloc(void *, size_t);#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG    static void (* __malloc_alloc_oom_handler)();#endifpublic:static void * allocate(size_t n){    void *result = malloc(n);   // 第一級配置器直接使用 malloc()    if (0 == result) result = oom_malloc(n);    return result;}static void deallocate(void *p, size_t /* n */){    free(p);    // 第一級配置器直接使用 free()}static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz){    void * result = realloc(p, new_sz); // 第一級配置器直接使用 realloc()    if (0 == result) result = oom_realloc(p, new_sz);    return result;}// 以下類似 C++ 的 set_new_handler().//这个函数的机制是,你可以要求系统在内存配置无法被满足时,调用一个你所指定的函数。 new_handler解决内存不足的特有模式。static void (* set_malloc_handler(void (*f)()))(){    void (* old)() = __malloc_alloc_oom_handler;    __malloc_alloc_oom_handler = f;    return(old);}};// malloc_alloc out-of-memory handling#ifndef __STL_STATIC_TEMPLATE_MEMBER_BUGtemplate <int inst>void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;#endiftemplate <int inst>void * __malloc_alloc_template<inst>::oom_malloc(size_t n){    void (* my_malloc_handler)();    void *result;    for (;;) {  // 不斷嘗試釋放、配置、再釋放、再配置…        my_malloc_handler = __malloc_alloc_oom_handler;      if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }        (*my_malloc_handler)();     // 呼叫處理常式,企圖釋放記憶體。        result = malloc(n);         // 再次嘗試配置記憶體。        if (result) return(result);    }}template <int inst>void * __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n){    void (* my_malloc_handler)();    void *result;    for (;;) {  // 不斷嘗試釋放、配置、再釋放、再配置…        my_malloc_handler = __malloc_alloc_oom_handler;        if (0 == my_malloc_handler) { __THROW_BAD_ALLOC; }        (*my_malloc_handler)(); // 呼叫處理常式,企圖釋放記憶體。        result = realloc(p, n); // 再次嘗試配置記憶體。        if (result) return(result);    }}typedef __malloc_alloc_template<0> malloc_alloc;