内存池实现相当的简单,由两个个主要部分组成 pheap,pfree,pool_struct,以及基本的内存池API
pheap: 内存块,它由pfree组织管理
pfree: 由pheap构成链表,它作为内存池实体单元
pool_struct: 内存池结构体
//pool.h文件
//=========================================================================
//于内存池中的实体(内存块)关联的回调函数,当实体释放时调用
typedef void (*pool_cleanup_t)(void *arg);
//单独内存分块
struct pheap
{
void *block; //实际的数据内存块
int size,used; //实际大小,使用大小
};
//带有释放内存毁掉函数的内存分块链表结点(内存池实体)
struct pfree
{
pool_cleanup_t f; //内存释放毁掉函数
void *arg;
struct pheap *heap; //单独内存分块
struct pfree *next; //下一个单独内存分块
};
//内存池--基于内存池实体。管理一个由内存池实体(pfree)组成的链表。
typedef struct pool_struct
{
int size; //内存池大小
struct pfree *cleanup; //链表首结点
struct pfree *cleanup_tail; //链表尾结点
struct pheap *heap;
#ifdef POOL_DEBUG //调试信息
char name[8], zone[32];
int lsize;
#endif
} _pool, *pool_t;
#ifdef POOL_DEBUG //调式调用函数版本定义宏
# define pool_new() _pool_new(__FILE__,__LINE__)
# define pool_heap(i) _pool_new_heap(i,__FILE__,__LINE__)
#else
# define pool_heap(i) _pool_new_heap(i,NULL,0)
# define pool_new() _pool_new(NULL,0)
#endif
//jabberd2内存池API函数定义
JABBERD2_API pool_t _pool_new(char *file, int line); //构建一个新的内存池
JABBERD2_API pool_t _pool_new_heap(int size, char *file, int line); //构建一个指定初始内存区块大小的内存池
JABBERD2_API void *pmalloc(pool_t, int size);//封装 malloc函数,内存从内存池中进行分配,自动完成释放
JABBERD2_API void *pmalloc_x(pool_t p, int size, char c); /* Wrapper around pmalloc which prefils buffer with c */
JABBERD2_API void *pmalloco(pool_t p, int size); /* YAPW for zeroing the block */
JABBERD2_API char *pstrdup(pool_t p, const char *src); /* wrapper around strdup, gains mem from pool */
JABBERD2_API char *pstrdupx(pool_t p, const char *src, int len); /* use given len */
JABBERD2_API void pool_stat(int full); /* print to stderr the changed pools and reset */
JABBERD2_API void pool_cleanup(pool_t p, pool_cleanup_t fn, void *arg); /* calls f(arg) before the pool is freed during cleanup */
JABBERD2_API void pool_free(pool_t p);//调用所有的内存释放回调函数,释放所有内存池中的数据,删除内存池本身
JABBERD2_API int pool_size(pool_t p); //返回内存中已分配的总字节数
//pool.c文件
//=========================================================================
//构建一个新的空内存池
pool_t _pool_new(char *zone, int line)
{
pool_t p;
while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
p->cleanup = NULL; //初始空链表
p->heap = NULL; //同上
p->size = 0;
#ifdef POOL_DEBUG
p->lsize = -1;
p->zone[0] = '\0';
snprintf(p->zone, sizeof(p->zone), "%s:%i", zone, line);
sprintf(p->name,"%X",(int)p);
if(pool__disturbed == NULL)
{
pool__disturbed = (xht)1; /* reentrancy flag! */
pool__disturbed = xhash_new(POOL_NUM);
}
if(pool__disturbed != (xht)1)
xhash_put(pool__disturbed,p->name,p);
#endif
return p;
}
//释放一个内存分块
static void _pool_heap_free(void *arg)
{
struct pheap *h = (struct pheap *)arg;
_pool__free(h->block); //free数据内存块
_pool__free(h); //free pheap结构体自身
}
//向内存池中添加内存池实体pfree
static void _pool_cleanup_append(pool_t p, struct pfree *pf)
{
struct pfree *cur;
if(p->cleanup == NULL)//空内存池时
{
p->cleanup = pf;
p->cleanup_tail = pf;
return;
}
//链表末尾添加新实体
cur = p->cleanup_tail;
cur->next = pf;
p->cleanup_tail = pf;
}
//创建一个内存池实体
static struct pfree *_pool_free(pool_t p, pool_cleanup_t f, void *arg)
{
struct pfree *ret;
//为内存池实体分配内存
while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
ret->f = f; //内存块释放回调函数
ret->arg = arg; //回调函数参数
ret->next = NULL;
return ret;
}
//创建一个内存块,并为其设置内存释放回调函数
static struct pheap *_pool_heap(pool_t p, int size)
{
struct pheap *ret; //数据内存块结构体
struct pfree *clean; //内存池实体
//分配内存数据块结构体内存
while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1);
//分配数据内存块内存
while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
ret->size = size; //指定数据内存块大小
p->size += size; //更新内存池总字节数
ret->used = 0;
//生成对应的内存池实体,_pool_heap_free为静态函数地址,ret为其调用参数
clean = _pool_free(p, _pool_heap_free, (void *)ret);
clean->heap = ret; /* for future use in finding used mem for pstrdup */
_pool_cleanup_append(p, clean);//将内存池实体,添加到内存池实体链表中
return ret;
}
//内存池内存请求函数
void *pmalloc(pool_t p, int size)
{
void *block;
if(p == NULL)
{
fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
abort();
}
//如果内存池中没有可用内存,或者申请的内存过大时,直接从进程堆中申请内存
if(p->heap == NULL || size > (p->heap->size / 2))
{
while((block = _pool__malloc(size)) == NULL) sleep(1); //直接从进程内存堆上分配
p->size += size; //递增内存池总字节数
_pool_cleanup_append(p, _pool_free(p, _pool__free, block));//生成相应的内存池实体,并添加到内存池实体链表中
return block;
}
/* we have to preserve boundaries, long story :) */
if(size >= 4)
while(p->heap->used&7) p->heap->used++;
/* if we don't fit in the old heap, replace it */
// 如果在现有内存块中没有足够的内存,重新申请一块
if(size > (p->heap->size - p->heap->used))
p->heap = _pool_heap(p, p->heap->size);
//当前内存块有剩余空间
block = (char *)p->heap->block + p->heap->used; //返回内存区块有效地址
p->heap->used += size; //更新内存区块使用情况
return block;
}
//对pmalloc进行封装并使用参数c的内容预填充新内存块
void *pmalloc_x(pool_t p, int size, char c)
{
void* result = pmalloc(p, size);
if (result != NULL)
memset(result, c, size);
return result;
}
//方便,安全(为结构体申请空白内存等)
void *pmalloco(pool_t p, int size)
{
void *block = pmalloc(p, size);
memset(block, 0, size);
return block;
}
阅读(1332) | 评论(1) | 转发(0) |