SGI一级空间配置器原理的简单介绍
SGI一级空间配置器里边提供给用户使用的接口就只有三个,allocate 、deallocate 和 reallocate。allocate函数用于申请空间,用户将需要的字节数传给该函数,然后在函数里边调用 malloc()函数来申请空间,如果申请成功,那么直接将这块空间的地址返回给用户。如果申请失败了,说明系统里边空间已经不足了,那么接下来的处理就稍微麻烦一点,需要使用一个oom_malloc函数来帮忙申请空间。
这个oom_malloc函数里边的实现跟C++中的new的实现比较相似。因为系统里边已经没有空间供我们申请了,所以只能将当前程序中的一些不需要的空间释放掉(还给系统),然后再调用malloc函数重新进行申请。系统是不知道哪部分空间是我们已经不需要了的,只有用户自己知道,所以,系统是不会主动帮我们释放空间的,释放空间的函数只有由我们用户自己来提供。如果用户没有提供这样一个函数,那么系统也就没法了,只能抛异常了。
有可能我们申请的空间比较大,调用一次释放空间的函数,释放的空间有可能还不足以提供给我们,所以,以上这个释放空间然后申请空间的过程应该是一个循环的过程,知道空间申请成功,循环就退出了。
reallocate 和 allocate 的实现很相似,基本就是多了一个参数,我就不重复讲了。deallocate 是用于释放空间的,它的实现非常简单,就是调用一下free()函数。
具体实现
#pragma once #include <new> #include <iostream> using namespace std; #define THROW_BAD_ALLOC cerr<<"out of memory"<<endl;exit(1) template <int inst> class Alloc_malloc_template { public: //Allocate用于申请空间 static void* Allocate(size_t n) { void* result = malloc(n); //申请失败,使用oom_malloc()重新尝试申请 if (result == NULL) Oom_malloc(n); return result; } //Deallocate用于释放空间 static void* Deallocate(void* p, size_t /* size*/) { free(p); } //Reallocate用于根据需要调整已经存在的空间的大小 static void* Reallocate(void* p, size_t size) { void* result = realloc(p, size); //申请失败,使用oom_realloc()尝试申请 if (result == NULL) Oom_realloc(p, size); return result; } //Set_malloc_handler函数是用于设置用户提供的释放空间的函数指针 static void(*Set_malloc_handler(void(*f)())) () { void(*old)() = _Malloc_alloc_oom_handler; _Malloc_alloc_oom_handler = f; return (old); } private: //通过用户提供的释放空间(释放自己已经不用了的空间)的函数不断的释放空间并检测 //直到释放出的空间足够分配给申请的空间 //如果用户没有提供释放空间的函数,则抛异常 static void* Oom_malloc(size_t size) { void* result; void(*My_malloc_handler)(); for (;;) { My_malloc_handler = _Malloc_alloc_oom_handler; if (0 == My_malloc_handler)//用户没有提供释放空间的函数 THROW_BAD_ALLOC; result = malloc(size); if (result) return result; } } static void* Oom_realloc(void* p, size_t size) { void* result; void(*my_malloc_handler) (); for (;;) { my_malloc_handler = _Malloc_alloc_oom_handler; if (0 == my_malloc_handler) THROW_BAD_ALLOC; result = realloc(p, size); if (result) return result; } } private: static void(*_Malloc_alloc_oom_handler)(); }; //类外初始化静态成员变量 _malloc_alloc_oom_handler template <int inst> void(* Alloc_malloc_template<inst>::_Malloc_alloc_oom_handler)() = 0;