Alloc.h
//Alloc.h负责内存空间的配置与释放
//Construct.h负责对象内容的构造与析构
//这两个头文件在memory文件中包含
#pragma once
typedef void(*HANDLER_FUNC)();
//一级空间配置器
template <int inst>
class __MallocAllocTemplate
{
public:
static void* Allocate(size_t size)//静态成员函数
{
void* result = malloc(size);
if (result == NULL){
result = __OomMalloc(size);
}
return result;
}
static void Deallocate(void* ptr)
{
free(ptr);
}
static void* Reallocate(void* ptr,size_t size)
{
void* result = realloc(ptr,size);
if (result == NULL){
result = __OomRealloc(ptr,size);
}
return result;
}
//分配内存失败处理函数的句柄函数指针,初值为NULL,客户端可以设定
static void(*__MallocAllocOomHandler)();
private:
static void* __OomMalloc(size_t size);
static void* __OomRealloc(void *p,size_t size);
// 模仿C++的set_new_handler();
// static void(*SetMallocHandler(void(*f)()))(){//函数
static HANDLER_FUNC SetMallocHandler(HANDLER_FUNC f){
HANDLER_FUNC old = __MallocAllocOomHandler;
__MallocAllocOomHandler = f;
return old;
}
};
template<int inst>
void (* __MallocAllocTemplate<inst>::__MallocAllocOomHandler)() = NULL;
template<int inst>
void* __MallocAllocTemplate<inst>::__OomMalloc(size_t size)
{
void(*myMallocHandler)();
void *result;
for (;;) {
myMallocHandler = __MallocAllocOomHandler;
if (0 == myMallocHandler) {//没有自定义内存异常处理函数,STL中抛异常
std::cout << "out of memory" << std::endl;
exit(-1);
}
(*myMallocHandler)();//调用自定义内存异常处理函数
result = malloc(size);
if (result) return(result);
}
}
template<int inst>
void* __MallocAllocTemplate<inst>::__OomRealloc(void *ptr,size_t size)
{
void(*myMallocHandler)();
void *result;
for (;;) {
myMallocHandler = __MallocAllocOomHandler;
if (0 == myMallocHandler) {
std::cout << "out of memory" << std::endl;
exit(-1);
}
(*myMallocHandler)();
result = realloc(ptr, size);
if (result)
return (result);
}
}
template<class T, class Alloc>
class SimpleAlloc
{
public:
static T *Allocate(size_t n)
{
return 0 == n ? 0 : (T*)Alloc::Allocate(n * sizeof (T));
}
static T *Allocate(void)
{
return (T*)Alloc::Allocate(sizeof (T));
}
static void Deallocate(T *ptr, size_t n)
{
if (0 != n) Alloc::Deallocate(ptr, n * sizeof (T));
}
static void Deallocate(T *ptr)
{
Alloc::Deallocate(ptr, sizeof (T));
}
};
//template <class Alloc>
//class debug_alloc {}
# ifdef __USE_MALLOC
typedef __MallocAllocTemplate<0> alloc;
# else
//二级空间配置器
enum{__ALIGN=8};
enum{__MAXBYTES=128};
enum{ __NFREELISTS = __MAXBYTES/__ALIGN};//自由链表的个数
//第一个参数用于多线程,第二个参数没有派上用场
template <bool threads, int inst>
class __DefaultAllocTemplate
{
private:
union Obj{
union Obj* freeLinkList;
char clientData[1];//给用户使用
};
static size_t FREELIST_INDEX(size_t size)//根据size决定使用几号自由链表
{
return ((size + (__ALIGN - 1)) / __ALIGN - 1);
}
static size_t ROUND_UP(size_t size) {//将size往上调整为8的倍数
return ((size + __ALIGN - 1) & ~(__ALIGN - 1));
}
public:
static void* Allocate(size_t size);
static void Deallocate(void* ptr,size_t size);
static void* Reallocate(void* p,size_t size);
private:
static char* ChunkAlloc(size_t size, size_t& Objs);
static void* Refill(size_t size);
public:
static char* _start;//内存池
static char* _end;
static size_t _heapSize;
static Obj* _freeList[__NFREELISTS];//指向自由链表
};
template <bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::_start = 0;
template <bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::_end = 0;
template <bool threads, int inst>
size_t __DefaultAllocTemplate<threads, inst>::_heapSize = 0;
template <bool threads, int inst>
typename __DefaultAllocTemplate<threads, inst>::Obj* __DefaultAllocTemplate<threads, inst>::_freeList[__NFREELISTS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
typedef __DefaultAllocTemplate<true, 0> alloc;
template <bool threads, int inst>
void* __DefaultAllocTemplate<threads, inst>::Allocate(size_t size)
{
if (size > __MAXBYTES){
return __MallocAllocTemplate<0>::Allocate(size);
}
size_t index = FREELIST_INDEX(size);
Obj* myFreeList = _freeList[index];//STL中用的是二级指针
if (myFreeList != NULL){//自由链表对应位置挂有内存块
_freeList[index] = myFreeList->freeLinkList;
return myFreeList;
}
//自由链表对应位置没有内存块,到内存池取
void *result = Refill(ROUND_UP(size));
return result;
}
template <bool threads, int inst>
void __DefaultAllocTemplate<threads, inst>::Deallocate(void* ptr,size_t size)
{
if (size > __MAXBYTES){//调用一级空间配置器
__MallocAllocTemplate<0>::Deallocate(ptr);
}
else{
size_t index = FREELIST_INDEX(size);
((Obj*)ptr)->freeLinkList = _freeList[index];
_freeList[index] = (Obj*)ptr;
}
}
template <bool threads, int inst>
void* __DefaultAllocTemplate<threads, inst>::Reallocate(void* p, size_t size)
{
}
//size此时已调至8的倍数,第二个参数必须是引用
template <bool threads, int inst>
char* __DefaultAllocTemplate<threads, inst>::ChunkAlloc(size_t size, size_t& Objs)
{
size_t TotalBytes =Objs*size;
size_t LeftBytes = _end - _start;
char* result=NULL;
if (TotalBytes <= LeftBytes){//内存池有满足需求的内存
result = _start;
_start += TotalBytes;
}
else{
if (LeftBytes < size){//内存池没有足够大,调用一级空间配置器
size_t requSize = 2 * TotalBytes + ROUND_UP(_heapSize >> 4);
int index = 0;
Obj* myfreeList=NULL;
if (LeftBytes>0){//内存池还有一些零头,挂到相应的位置(它一定是8的倍数)
myfreeList = (Obj*)_start;
index = FREELIST_INDEX(LeftBytes);
myfreeList->freeLinkList = _freeList[index];
_freeList[index] = myfreeList;
}
//调用一级空间配置器配置内存池
_start = (char*)__MallocAllocTemplate<0>::Allocate(requSize);
if (_start == 0){//一级空间配置器分配失败,到自由链表中试着取比需要大小内存更大的内存
index = FREELIST_INDEX(size);
for (index; index < __NFREELISTS; ++index){
if (_freeList[index] != NULL){
_start = (char*)_freeList[index];
_freeList[index]=((Obj*)_start)->freeLinkList;
_end = _start + (index+1)*__ALIGN;
return( ChunkAlloc(size, Objs));
}
}
_end = NULL;//没有任何空间可用
_start = (char*)__MallocAllocTemplate<0>::Allocate(requSize);
}
_end = _start + requSize;
_heapSize += requSize;
return (ChunkAlloc(size,Objs));
}
else{//内存池能满足一个空间的大小
Objs = LeftBytes / size;
TotalBytes = Objs * size;
result = _start;
_start += TotalBytes;
}
}
return result;
}
template <bool threads, int inst>
void* __DefaultAllocTemplate<threads, inst>::Refill(size_t size)
{
size_t Objs = 20;//想申请20个对象的大小挂到自由链表中
char* chunk = ChunkAlloc(size,Objs);//拿到一大块的内存准备往挂到自由链表
if (Objs == 1)
return chunk;
Obj* result = (Obj*)chunk;
Obj* curObj = NULL;
Obj* nextObj = NULL;
size_t index = FREELIST_INDEX(size);
_freeList[index] = nextObj = (Obj*)(chunk + size);
for (size_t i = 0; i < Objs-2; ++i){
curObj = nextObj;
nextObj = curObj + 1;
curObj->freeLinkList = nextObj;
}
curObj->freeLinkList = NULL;
return result;
}
#endifTest.cpp
#include "Alloc.h"
void Testalloc1()
{
/*char* ptr1 = new char;
char* ptr2 = new char[4];*/
std::cout << " 测试调用一级配置器分配内存 " << std::endl;
char*p1 = SimpleAlloc< char, alloc>::Allocate(129);
p1 = SimpleAlloc< char, alloc>::Allocate(8);
SimpleAlloc<char, alloc>::Deallocate(p1, 129);
// 测试调用二级配置器分配内存
std::cout << " 测试调用二级配置器分配内存 " << std::endl;
char*p2 = SimpleAlloc< char, alloc>::Allocate(128);
char*p3 = SimpleAlloc< char, alloc>::Allocate(128);
char*p4 = SimpleAlloc< char, alloc>::Allocate(128);
char*p5 = SimpleAlloc< char, alloc>::Allocate(128);
SimpleAlloc<char, alloc>::Deallocate(p2, 128);
SimpleAlloc<char, alloc>::Deallocate(p3, 128);
SimpleAlloc<char, alloc>::Deallocate(p4, 128);
SimpleAlloc<char, alloc>::Deallocate(p5, 128);
for (int i = 0; i < 21; ++i){
printf(" 测试第%d次分配 \n", i + 1);
char*p = SimpleAlloc< char, alloc>::Allocate(128);
}
}
void TestAlloc2()
{
// 测试特殊场景
std::cout<<" 测试内存池空间不足分配个 "<<std::endl ; // 8*20->8*2->320
char*p1 = SimpleAlloc< char, alloc>::Allocate (8);
char*p2 = SimpleAlloc< char, alloc>::Allocate(8);
std::cout << " 测试内存池空间不足,系统堆进行分配 " << std::endl;
char*p3 = SimpleAlloc< char, alloc>::Allocate(12);
}
void TestAlloc3()
{
std::cout << " 测试系统堆内存耗尽 " << std::endl;
SimpleAlloc<char, alloc>::Allocate(1024 * 1024 * 1024);
SimpleAlloc<char, alloc>::Allocate(1024 * 1024);
// 不好测试,说明系统管理小块内存的能力还是很强的。
for (int i = 0; i < 100000; ++i ){
char*p1 = SimpleAlloc< char, alloc>::Allocate (128);
}
}
void TestAlloc()
{
//TestAlloc1();
//TestAlloc2();
TestAlloc3();
}本文出自 “零蛋蛋” 博客,谢绝转载!
原文:http://lingdandan.blog.51cto.com/10697032/1837109