C 内存池的实现

  总体的设计思路:

      首先按照内存块的大小申请N*块大小的连续内存区域。

      构造内存块的双向链表,有2种,一种是空闲链表;另外一种为已经使用的链表。该双向链表也是一块固定大小的内存区域,每个链表节点存储了当前内存块的地址、该节点上一个节点以及下一个节点。

     

#define ut_base(TYPE) \
    struct {          \
        TYPE *next;   \
        TYPE *prev;   \
    }__attribute__((packed))
/**********************
 * define memory block struct _block
 * *******************/
typedef struct _block{
    char *data;
    ut_base(struct _block) base;
}__attribute__((packed)) block;

 

      内存池中存储链表的起始地址、内存块的起始地址、空闲链表的节点数、空闲链表的开始节点以及结束节点、已使用链表的节点的开始节点以及结束节点。

 

typedef struct _mem_pool
{
    unsigned int blockCount;
    unsigned int blockSize;
    unsigned int freeSize;
    unsigned int freeCount;
    struct _block *freeH;
    struct _block *freeT;
    struct _block *usedH;
    struct _block *usedT;
    struct _block *pBlockHead;
    char *pDataHead;
}__attribute__((packed)) mem_pool;

 

 

mem_pool.h

#define increment  64
/********************
 * define base list 
 * *****************/
#define ut_base(TYPE) \
    struct {          \
        TYPE *next;   \
        TYPE *prev;   \
    }__attribute__((packed))
/**********************
 * define memory block struct _block
 * *******************/
typedef struct _block{
    char *data;
    ut_base(struct _block) base;
}__attribute__((packed)) block;
/********************
 * define memory pool
 * *****************/
typedef struct _mem_pool
{
    unsigned int blockCount;
    unsigned int blockSize;
    unsigned int freeSize;
    unsigned int freeCount;
    struct _block *freeH;
    struct _block *freeT;
    struct _block *usedH;
    struct _block *usedT;
    struct _block *pBlockHead;
    char *pDataHead;
}__attribute__((packed)) mem_pool;
/***********************
 * init a memory pool
 * *******************/
int pool_init(int blockSize,int blockCount);
/*********************
 * add block to mem_pool
 * ******************/
int pool_block(size_t unitSize,int blockCount);
/**********************
 * alloc memory from memory pool
 * ********************/
char *pool_alloc(size_t allocSize);
/************************
 * recyc memory from memory pool
 * ********************/
int pool_recyc();
/**************************
 * free all memory to operation system
 * ***********************/
void pool_free();
/***************************
 * prt all list of memory pool
 * ************************/
void pool_prt();

 

mem_pool.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mem_pool.h"
static mem_pool pool;
int pool_init(int blockSize,int blockCount)
{
    mem_pool *mp=&pool;
    int flag=0;
    mp->blockCount=mp->freeCount=blockCount;
    mp->blockSize=blockSize;
    mp->freeH=mp->freeT=NULL;
    mp->usedH=mp->usedT=NULL;
    flag=pool_block(blockSize,blockCount);
    if(flag>0){fprintf(stderr," pool_init error\n");return 1;}
    return 0;
}
int pool_block(size_t unitSize,int blockCount)
{
    mem_pool *mp=&pool;
    int i=0;
    mp->pBlockHead=(block *)malloc(sizeof(block)*blockCount);
    mp->pDataHead=(char *)malloc(sizeof(char)*unitSize*blockCount);
    memset(mp->pDataHead,'\0',sizeof(char)*unitSize*blockCount);
    mp->blockCount=blockCount;
    mp->freeSize=sizeof(char)*unitSize*blockCount;
    block *bk=NULL;
    for(;i<blockCount;i++)
    {
      bk=(block *)mp->pBlockHead+(sizeof(block)*i);
      char *data=mp->pDataHead+(sizeof(char)*unitSize*i);
      bk->base.next=NULL;
      bk->base.prev=mp->freeT;
      if(mp->freeH==NULL)
      {
          mp->freeH=mp->freeT=bk;
      }
      else
      {
          mp->freeT->base.next=bk;
          mp->freeT=bk;
      }
      bk->data=data;
    }
    printf(" ---------------pool_block(size_t unitSize=%d,int blockCount=%d)--------------\n",unitSize,blockCount);
    printf("        mp->freeH : %p,mp->freeH->base.prev : %p\n",mp->freeH,mp->freeH->base.prev);
    printf("        mp->freeT : %p,mp->freeT->base.next : %p\n",mp->freeT,mp->freeT->base.next);
    return 0;
}
char *pool_alloc(size_t allocSize)
{
    mem_pool *mp=&pool;
    int allocCount=0;
    int i=0;
    if(mp->freeT==NULL)
    {
        pool_init(mp->blockSize,mp->blockCount);
        printf("\t execute pool_init() \n");
    }
    if((allocSize%(mp->blockSize))==0)
    {
       allocCount=allocSize/(mp->blockSize);
    }
    else
    {
        allocCount=allocSize/(mp->blockSize)+1;
    }
    block *bk=mp->freeT;
    for(;i<allocCount;i++)
    {
        block *prev=mp->freeT->base.prev;
        bk->base.prev=NULL;
        bk->base.next=NULL;
        memset(bk->data,'\0',mp->blockSize);
       // printf(" %d,mp->freeT : %p,mp->freeT->base.prev :%p\n",i,mp->freeT,mp->freeT->base.prev);
        if(mp->usedH==NULL)
        {
              mp->usedH=mp->usedT=bk;
              mp->usedH->base.prev=NULL;
        }
        else
        {  
              bk->base.prev=mp->usedT;
              mp->usedT->base.next=bk;
              mp->usedT=bk;
              //printf("bk :%p,bk->base.prev :%p,bk->base.next :%p\n",bk,bk->base.prev,bk->base.next);
        }
        //memset(mp->usedT->data,'\0',mp->blockSize);
        mp->freeT=prev;
        //printf("mp->freeT : %p\n",mp->freeT);
        bk=mp->freeT;
        //printf(" %d,mp->freeT : %p\n",i,mp->freeT);
    }
    mp->freeT->base.next=NULL;
    //mp->freeT=mp->pBlockHead+(sizeof(block)*(mp->blockCount-allocCount));
    mp->freeCount=mp->freeCount-allocCount;
    mp->freeSize=(mp->blockSize)*(mp->blockCount-allocCount);
    //memset(mp->pDataHead+mp->freeSize,'\0',allocCount);
    printf(" --------pool_alloc(size_t allocSize=%d)--------\n",allocSize); 
    printf("        mp->freeH = %p,mp->freeT = %p\n",mp->freeH,mp->freeT);
    printf("        mp->usedH = %p,mp->usedT = %p\n",mp->usedH,mp->usedT);
    return mp->pDataHead+(mp->freeSize);
}
void pool_prt()
{
    mem_pool *p=&pool;
    block *fr=p->freeH;
    block *us=p->usedH;
    int i=0;
    printf(" \t***********free list->\n");
    while(fr!=NULL)
    {
        printf("\t(current  = %p,data=%p)",fr,fr->data);
        printf(",prev = %p",fr->base.prev);
        printf(",next = %p\n",fr->base.next);
       // printf("\t  ## :current->data =%p",fr->data);
       // printf(",prev->data = %p",fr->base.prev->data);
       // printf(",next->data = %p\n",fr->base.next->data);
        fr=fr->base.next;
        i++;
    }
    printf(" \tfreelist length = %d\n",i);
    i=0;
    printf(" \t p->freeH = %p,p->freeT = %p\n",p->freeH,p->freeT);
    printf(" \t**********used list->\n");
    while(us!=NULL)
    {   
       printf("\t(current  = %p,data=%p",us,us->data);
       printf(",prev = %p",us->base.prev);
       printf(",next = %p\n",us->base.next);
      // printf("\t  ## :current->data =%p",us->data);
       //printf(",prev->data = %p",us->base.prev->data);
       //printf(",next->data = %p\n",us->base.next->data);
       us=us->base.next;
       i++;
    } 
    printf(" \tusedlist length = %d\n",i);
    printf(" \tp->usedH  = %p,p->usedT = %p\n",p->usedH,p->usedT);
    printf("\n");
}
void pool_free()
{
    mem_pool *p=&pool;
    free(p->pBlockHead);
    free(p->pDataHead);
    p->pBlockHead=NULL;
    p->pDataHead=NULL;
    printf("\t mem_pool free \n");
}
int pool_recyc(size_t freeSize)
{
    mem_pool *mp=&pool;
    int cyc=0,i=0;
    if(freeSize>(mp->blockSize*mp->blockCount))
    {
        fprintf(stderr," freeSize is over all memory size in memory pool\n");
        return 1;
    }
    if((freeSize%mp->blockSize)==0)
    {
        cyc=freeSize/(mp->blockSize);
    }
    else
    {
        cyc=(freeSize/mp->blockSize)+1;
    }
    printf(" --------pool_recyc(size_t freeize=%d)--------\n",freeSize);
    printf("        recyc block count = %d\n",cyc);
    printf("        begin: mp->freeH = %p,mp->freeT = %p\n",mp->freeH,mp->freeT);
    printf("        begin: mp->usedH = %p,mp->usedT = %p\n",mp->usedH,mp->usedT);
    printf("        begin: mp->freeCount = %d,mp->freeSize = %d\n",mp->freeCount,mp->freeSize);
    if(mp->usedH==NULL)
    {
        fprintf(stderr," all block is not used in memory pool\n");
        return 1;
    }
    block *cur=mp->usedT;
    for(;i<cyc;i++)
    {
         //link a block to free list
         block *prev=cur->base.prev;
         mp->freeT->base.next=cur;
         cur->base.prev=mp->freeT;
         memset(cur->data,'\0',mp->blockSize);
         mp->freeT=cur;
         //mp->usedT=mp->usedT->base.prev;
         cur=prev;
         mp->usedT=prev;
         //remove a block from used 
    }
    if(cyc==(mp->blockCount-mp->freeCount))
    {
        mp->usedH=mp->usedT=NULL;
    }
    if(mp->usedT!=NULL)
    {
        if(mp->usedT==mp->usedH)
        {
            mp->usedH->base.prev=NULL;
            mp->usedT->base.next=NULL;
        }
    }
    mp->freeT->base.next=NULL;
    mp->freeCount=mp->freeCount+cyc;
    mp->freeSize=mp->freeSize+(mp->blockSize*cyc);
    printf("        end: mp->freeH = %p,mp->freeT = %p\n",mp->freeH,mp->freeT);
    printf("        end: mp->usedH = %p,mp->usedT = %p\n",mp->usedH,mp->usedT);
    printf("        end: mp->freeCount = %d,mp->freeSize = %d\n",mp->freeCount,mp->freeSize);
    return 0;
}
int main(void)
{
    printf(" pool_init(%d,%d) = %d\n",4,100,pool_init(5,10));
    pool_prt();
    char *p=pool_alloc(14);
    memset(p,'1',13);
    printf(" char *p =%s\n",p);
    pool_prt();
    pool_recyc(12);
    pool_prt();
    char *p1=pool_alloc(6);
    memset(p1,'8',5);
    printf("char *p1 = %s\n",p1);
    pool_prt();
    pool_recyc(3);
    printf(" char *p =%s\n",p);
    pool_prt();
    pool_free();
    return 0;
}

 

posted @ 2015-06-10 10:36  一个万能盒子叫数据库  阅读(838)  评论(0编辑  收藏  举报