jabberd2的内存池

jabberd2的内存池

 

闲来无事对jabberd2服务器阅读了下,每次读C++代码,都首先花费一些额外的时间领会代码作者的抽象世界概念堆砌当中,C则不同,直入主题,心理上不会有任何负担,不用徒劳辗转在不同的世界理解和哲思之中,又一次拜倒在C的简洁明了之下
^^废话不多说了开始我们的内容:
内存池实现相当的简单,由两个个主要部分组成 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  * =  ( 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;  // 内存块释放回调函数
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;
}


 

 

 

 

你可能感兴趣的:(jabberd2的内存池)