SGI空间配置器

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_type
template <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_T
inline 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)();

#endif

public:

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_BUG
template <int inst>
void (* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;
#endif

template <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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值