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;