一,一级配置器的源代码
/**
* 注意:没有类型参数,非类别参数inst完全没有用到
*/
template<int inst>
class _malloc_alloc_template{
private:
//下面的函数用来处理内存不足的情况
//oom:out of memory
static void *oom_malloc(size_t);
static void *oom_realloc(void *, size_t);
static void (*_malloc_alloc_oom_handler)();
public:
static void (* set_malloc_handler(void(*f)))();
static void *allocate(size_t){
static void deallocate(void *, size_t);
static void *reallocate(void *, size_t);
};
/**
* 初始值为0,由用户指定内存不足时的处理函数
*/
template<int inst>
void (*_malloc_alloc_template<int inst>::_malloc_alloc_oom_handler)() = 0;
/**
* 使用一级配置器获取内存
*/
template<int inst>
void *_malloc_alloc_template<int inst>::allocate(size_t n){
//一级配置器直接使用malloc()来获取内存
void *result = malloc(n);
//内存请求得不到满足时,调用oom_malloc()
if(0 == result){
result = oom_malloc(n);
}
return result;
}
/**
* 使用一级配置器释放内存
*/
template<int inst>
void _malloc_alloc_template<int inst>::deallocate(void *p, size_t n){
//一级配置器直接使用free(),来释放内存
free(p);
}
/**
* 使用一级配置器对申请的内存,进行大小调整
*/
template<int inst>
void *_malloc_alloc_template<int inst>::reallocate(void *p, size_t new_sz){
//一级配置器直接使用realloc()
void *result = realloc(p, new_sz);
//当要求无法满足时,调用oom_realloc()
if(0 == result){
result = oom_realloc(p, new_sz);
}
return result;
}
/**
* 第一次分配内存不成功,会调用这个函数,它会不断的调用"内存不足处理程序",期望在
* 某次调用之后,获得足够的内存
*/
template<int inst>
void *_malloc_alloc_template<int 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;
}
}
}
二,一级配置器的工作原理
一级配置器使用malloc()、free()、realloc()等C函数执行实际的内存配置、释放、重配置操作。SGI第一级配置器allocate()和realloc()都是在调用malloc()和realloc()不成功后,改调用oom_malloc()和oom_realloc()。后两者都有内循环,不断调用"内存不足处理函数",期望在某次调用之后,获得足够的内存。但如果"内存不足处理函数"没有被用户设置,就会调用_THROW_BAD_ALLOC,丢出bad_alloc异常或利用exit(1)终止程序。
三,一级配置器实现类似C++ new-handler机制
1,C++ new-handler机制
在申请内存的需求得不到满足时,调用一个客户端指定的函数。换句话说,一旦new无法完成任务,在丢出bad_alloc异常之前,会先调用客户端指定的函数,该指定的函数称为new-handler。
2,SGI使用malloc来配置内存,因此,SGI不能直接使用C++的set_new_handler(),必须仿真一个类似的set_malloc_handler()函数,来实现类似new-handler机制。
static void (*set_malloc_handler(void(*f)))();{
void (*old)() = _malloc_alloc_oom_handler;
_malloc_alloc_oom_handler = f;
return (old);
}