/*
* C内存池实现代码
* 作者:WDL
* 出处:http://blog.csdn.net/wuleibilly3
* 转载请注明本博客
*/
//内存池
typedef struct _MemTable MemTable;
typedef struct _MemPool MemPool;
typedef struct _MemNode MemNode;
typedef struct _CheckAvail CheckAvail;
#define MIN_MEM_BLOCK 12 //最小内存块 最小不得低于12
#define MAX_MEM_BLOCK 128 //最大内存块
#define SIZE_TO_INDEX(a) ((((DATA_ALIGN(a,4))-MIN_MEM_BLOCK)/4)+1) //获得数据大小所对应的索引
#define INDEX_TO_SIZE(a) (MIN_MEM_BLOCK+4*((a)-1)) //获得索引所对应的数据大小
#define MAX_INDEX SIZE_TO_INDEX(MAX_MEM_BLOCK)+1 //最大索引
#define INIT_BLOCK_SIZE 10 //最初内存块的大小 以后根据递增申请内存
#define DATA_ALIGN(a,b) (((a) + ((b) - 1)) & ~((b) - 1)) //数据对齐
//情况检测结构体
typedef struct _CheckAvail{
int flag;
MemNode* data;
}CheckAvail;
//0号结点
typedef struct _MemZeroNode{
struct _MemZeroNode *next;
struct _MemZeroNode *up;
int is_avail_flag;
char mem_data[1];
}MemZeroNode;
typedef struct _MemBlock{
MemNode* parent; //它是哪个挂接表结点的儿子?
int is_avail_flag; //标志 高位16字节存放 是否可用 低位16字节存放 对应索引
char mem_data[1]; //数据
}MemBlock;
typedef struct _MemNode{
struct _MemNode *next; //指向下一块
char* pfree_avail; //可用空间起始
char* pend; //可用空间结束
int num_free_block; //可用块数
int num_mem_size; //内存大小
int num_block_total; //块数总计
int num_block_size; //单个块大小
MemBlock* block; //具体可用内存块
}MemNode;
//内存分配表
typedef struct _MemTable{
int num_maxindex; //最大索引
int *free[MAX_INDEX]; //可用内存表
int num_indexblockcount[MAX_INDEX]; //每个索引对应挂接内存块大小
}MemTable;
//内存池
typedef struct _MemPool{
MemTable data; //数据 内存池
}MemPool;
//初始化内存池
void InitMemPool();
//销毁内存池
void DestoryMemPool();
//获取可用内存
void* MemAlloc(int size);
//释放内存
void MemFree(void* p);
MemPool mem_pool;
CheckAvail check_avail;
//初始化挂接块数据
void InitHangUpBlock(MemNode* memnode,int blockcount,int index){
memnode->next = NULL;
memnode->num_block_size = INDEX_TO_SIZE(index); //单个块
memnode->num_block_total = blockcount*INIT_BLOCK_SIZE; //可用内存块总计
memnode->num_mem_size = memnode->num_block_total * memnode->num_block_size; //申请内存块内存大小
memnode->block = (MemBlock*)malloc( memnode->num_mem_size+1 ); //申请内存块
memnode->num_free_block = memnode->num_block_total;
memset(memnode->block,0,memnode->num_mem_size+1 ); //初始化挂接块
memnode->pfree_avail = (char*)memnode->block; //起始地址
memnode->pend = ((char*)memnode->block+memnode->num_mem_size); //结束地址
}
//初始化
void InitMemPool(){
int i = 0;
//0号表 用来挂接大于MAX_MEM_BLOCK的内存块
mem_pool.data.free[0] = (int*)malloc(sizeof(MemZeroNode));
memset(mem_pool.data.free[0],0,sizeof(MemZeroNode));
//首先初始化内存表
for(i = 1 ;i < MAX_INDEX ;i++){
mem_pool.data.free[i] = (int*)malloc(sizeof(MemNode));
mem_pool.data.num_indexblockcount[i] = 1;
memset(mem_pool.data.free[i],0,sizeof(MemNode));
//初始化挂接块数据
InitHangUpBlock((MemNode*)mem_pool.data.free[i],mem_pool.data.num_indexblockcount[i],i);
}
mem_pool.data.num_maxindex = MAX_INDEX;
}
//检测可用内存块
void CheckAvailBlock(MemNode* mem_node){
MemNode* temp;
int flag = 0;
for(temp = mem_node;temp != NULL; temp=temp->next){ //没有内存块可用
if((temp->pend-temp->pfree_avail)>0) break;
if(temp->num_free_block > 0){
check_avail.flag = 2;
check_avail.data = temp;
flag = 1;
}
}
if(temp != NULL){
check_avail.flag = 1;
check_avail.data = temp;
}else{
//二次检测
if(flag == 1){
return;
}else{
check_avail.flag = 3;
//没有内存块了 需要申请
}
}
}
//清空初始化内存检测
void InitCheckAvailBlock(){
check_avail.flag = 0;
check_avail.data = NULL;
}
//申请新的内存块
MemNode* NewMemBlock(int index){
MemNode *temp,*mem;
mem_pool.data.num_indexblockcount[index]++;
mem = (MemNode*)mem_pool.data.free[index];
for(;mem->next!=NULL;mem=mem->next); //循环到挂接表尾
temp = (MemNode*)malloc(sizeof(MemNode)); //申请新的结点
mem->next = temp; //挂接新的结点
//初始化挂接块数据
InitHangUpBlock(temp,mem_pool.data.num_indexblockcount[index],index);
return temp;
}
//0号表挂接
void* ZeroHangUp(int size){
MemZeroNode *mem,*temp;
int realsize = 0;
realsize = size + sizeof(MemZeroNode)-4;
mem = (MemZeroNode*)mem_pool.data.free[0];
temp = (MemZeroNode*)malloc(realsize); //申请新内存
temp->is_avail_flag = 0;
temp->next = mem->next; // 挂接
temp->up = mem;
if(mem->next!=NULL) mem->next->up = temp;
mem->next = temp;
return (void*)temp->mem_data;
}
//分配内存
void* MemAlloc(int size){
int realsize = 0;
int index = 0;
int flag = 0;
MemNode* mem_node;
if(size == 0) return NULL;
realsize = size + sizeof(MemBlock)-4; //0-3字节存储父结点 4-7字节要用来存可用标志位
//8-11字节存储自己
if(realsize > MAX_MEM_BLOCK){
return ZeroHangUp(size); //超过最大块 MAX_MEM_BLOCK 转到0号表进行挂接
}
index = SIZE_TO_INDEX(realsize);
mem_node = (MemNode*)mem_pool.data.free[index]; //根据索引获得挂接表的位置
InitCheckAvailBlock();
CheckAvailBlock(mem_node);
flag = check_avail.flag;
if(flag == 1){
//情况1 直接可用 O(1)
MemBlock* mem = NULL;
mem_node = check_avail.data;
mem = (MemBlock*)(mem_node->pend-INDEX_TO_SIZE(index)) ;
mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用
mem->is_avail_flag |= index; //标记所属索引
mem->parent = mem_node;
mem_node->pend -= INDEX_TO_SIZE(index);
mem_node->num_free_block--; //可用块数 -1
return (void*)mem->mem_data;
}else if(flag == 2){
//情况2 不直接可用 但是有残余的释放空间可用 O(n)
MemBlock* mem = NULL;
char *mem_start,*mem_end;
mem_node = check_avail.data;
mem_start = mem_node->pfree_avail;
mem_end = mem_node->pfree_avail+mem_node->num_mem_size;
for(;mem_start != mem_end;mem_start += INDEX_TO_SIZE(index)){ //遍历结点所有的挂接块
mem = (MemBlock*)mem_start;
if((mem->is_avail_flag&0xffff0000) == 0){ //检测是否可用
//这块内存可以被用来使用
mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用
//mem->is_avail_flag |= index; //标记所属索引
//mem->parent = mem_node;
mem_node->num_free_block--; //可用块数 -1
return (void*)mem->mem_data;
}
}
}else if(flag == 3){
//情况3 新申请的内存块
MemBlock* mem = NULL;
mem_node = NewMemBlock(index);
mem = (MemBlock*)(mem_node->pend-INDEX_TO_SIZE(index)) ;
mem->is_avail_flag |= 0xffff0000; //标记该内存块已经被使用
mem->is_avail_flag |= index; //标记所属索引
mem->parent = mem_node;
mem_node->pend -= INDEX_TO_SIZE(index);
mem_node->num_free_block--; //可用块数 -1
return (void*)mem->mem_data;
}
return NULL; //常理说 不可能走到这里
}
//释放内存
void MemFree(void* p){
int flag = *(int*)((char*)p-sizeof(int));
if((flag & 0x0000ffff) != 0){
MemBlock* mem = NULL;
*(int*)((char*)p-sizeof(int)) &= 0x0000ffff; //直接标志可被使用 不释放
//可用内存块 + 1
mem = (MemBlock*)((char*)p-sizeof(int)-sizeof(MemNode*));
mem->parent->num_free_block++;
}else{ //大于MAX_MEM_BLOCK的内存
MemZeroNode *mem = (MemZeroNode*)((char*)p-sizeof(MemZeroNode*)*2-sizeof(int));
mem->up->next = mem->next;
if(mem->next != NULL) mem->next->up = mem->up;
free(mem);
mem = NULL;
}
}
void DestoryMemPool(){
int i ;
MemZeroNode *mem = (MemZeroNode*)mem_pool.data.free[0];
//销毁0号挂接表
for(;mem != NULL;){
MemZeroNode *temp;
temp = mem;
mem = mem->next;
free(temp);
temp = NULL;
}
//销毁其它
for(i = 1;i < MAX_INDEX;i++){
MemNode *mem_node = (MemNode*)mem_pool.data.free[i];
for(;mem_node != NULL;){
MemNode *temp;
temp = mem_node;
free(temp->block); //释放具体内存块
temp->block = NULL;
mem_node = mem_node->next;
free(temp); //释放挂接表结点
temp = NULL;
}
}
}