内存池 实现源码--版本三

本文详细介绍了内存池的实现原理及优化技术,包括长度不固定、可分配、可回收的特性,采用链式查找和红黑树查找提高性能。通过多线程安全的内存分配与释放,有效管理内存资源,提升程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现长度不固定 ,可分配,可回收,

只用于学习,性能太差,

分配大小时查找使用的是链式,下个版本收为红黑树查找


list.h

// Copyright 2012 Tilera Corporation. All Rights Reserved.
//
//   The source code contained or described herein and all documents
//   related to the source code ("Material") are owned by Tilera
//   Corporation or its suppliers or licensors.  Title to the Material
//   remains with Tilera Corporation or its suppliers and licensors. The
//   software is licensed under the Tilera MDE License.
//
//   Unless otherwise agreed by Tilera in writing, you may not remove or
//   alter this notice or any other notice embedded in Materials by Tilera
//   or Tilera's suppliers or licensors in any way.
//
//

#ifndef _LIST_H_INCLUDED_
#define _LIST_H_INCLUDED_

#ifdef __cplusplus
extern "C" {
#endif 

// ****************************************************************************

struct list_head {
  struct list_head *prev;
  struct list_head *next;
};

// ****************************************************************************
#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

#define offset(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({			\
        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
        (type *)( (char *)__mptr - offset(type,member) );})

#define list_entry(ptr, type, member) container_of(ptr, type, member)

/**
 * list_for_each_entry_safe - iterate over list of given type safe against 
 * removal of list entry
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))


/**
 * list_for_each_entry	-	iterate over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)				\
	for (pos = list_entry((head)->next, typeof(*pos), member);	\
	     tmc_mem_prefetch(pos->member.next, sizeof(*pos)), &pos->member != (head); 	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))


		 
/**
 * list_for_each_exit_safe - iterate over list of given type safe against 
 * removal of list entry
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_exit_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
		n = list_entry(pos->member.prev, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))


/**
 * list_for_each_exit	-	iterate over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_exit(pos, head, member)				\
	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
	     tmc_mem_prefetch(pos->member.prev, sizeof(*pos)), &pos->member != (head); 	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))


// ****************************************************************************

static inline void
INIT_LIST_HEAD(struct list_head *list)
{
  list->prev = list;
  list->next = list;
}

static inline int
list_empty(const struct list_head *head)
{
  return head->next == head;
}

static inline void
__list_add(struct list_head *new,
           struct list_head *prev,
           struct list_head *next)
{
  next->prev = new;
  new->next = next;
  new->prev = prev;
  prev->next = new;
}

static inline void
list_add_head(struct list_head *new,
         struct list_head *head)
{
  __list_add(new, head, head->next);
}

static inline void
list_add_tail(struct list_head *new,
              struct list_head *head)
{
  __list_add(new, head->prev, head);
}

static inline void
__list_del(struct list_head *prev,
           struct list_head *next)
{
  next->prev = prev;
  prev->next = next;
}

static inline void
list_del(struct list_head *entry)
{
  __list_del(entry->prev, entry->next);
  entry->next = entry;
  entry->prev = entry;
}


static inline void
list_move_head (struct list_head *list, struct list_head *head)
{
	list_del (list);
	list_add_head (list, head);
}


static inline void
list_move_tail (struct list_head *list, struct list_head *head)
{
	list_del (list);
	list_add_tail (list, head);
}


static inline int
list_set_empty (struct list_head *head)
{
	return (head->next == head);
}
// ****************************************************************************

#ifdef __cplusplus
}
#endif  // cplusplus 

#endif  //  

// ****************************************************************************

main.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mem_pool.h"

void *mem_p_show_list(mem_pool_o *mem_pool);

int OBJ_COUNT=5;
int main(int argc, const char *argv[])
{
	mem_pool_o *mem_pool=NULL;
	struct timeval tval;
	int sec =0;
	if(argc !=2){
		return 0;
	}
	OBJ_COUNT = atoi(argv[1]);
	mem_pool = mem_p_obj_create(1024, OBJ_COUNT, 10, "asdf");
	if(mem_pool == NULL){
		printf("create fail\n");
		return 0;
	}
	char *b[OBJ_COUNT+5];
	int i=1;
	gettimeofday(&tval, NULL);
	sec = tval.tv_usec;

	for(i=0; i<OBJ_COUNT; i++)
	{
		b[i]=mem_p_obj_malloc(mem_pool, 1024);
		if(b[i]==NULL)
		{
			printf("%d malloc error\n", i);
		}
	}
	gettimeofday(&tval, NULL);
	printf("%d\n", tval.tv_usec -sec);
	//mem_p_obj_free(b[3]);
	//mem_p_obj_free(b[4]);
	//mem_p_show_list(mem_pool);
	for(i=0; i<OBJ_COUNT; i++){
		mem_p_obj_free(b[i]);
	}
	/*
	for(i=OBJ_COUNT; i<OBJ_COUNT+5; i++){
		b[i]=mem_p_obj_malloc(mem_pool, 500*(i+1));
		if(b[i]==NULL){
			printf("%d malloc error 2\n", i);
		}
	}
	*/
	mem_p_obj_destroy(mem_pool);

	
	gettimeofday(&tval, NULL);
	sec = tval.tv_usec;
	for(i=0; i<OBJ_COUNT; i++){
		b[i]=malloc(1024);
		if(b[i]==NULL){
			printf("%d malloc error\n", i);
		}
	}
	gettimeofday(&tval, NULL);
	printf("%d\n", tval.tv_usec -sec);
	for(i=0; i<OBJ_COUNT; i++){
		if(b[i]!=NULL){
			free(b[i]);
		}
	}
    return 0;
}

mem_pool.h

#ifndef _MEM_POOL_H_INCLUDED_
#define _MEM_POOL_H_INCLUDED_

#ifdef __cplusplus
extern "C" {
#endif 

#include "list.h"

typedef struct mem_pool_obj
{
	void  *unused_hash;//未使用块信息表
	struct list_head  pool_list;//buff内存块表
	unsigned int     inc_count;//可否自增加
	unsigned int     objcount;//最小块个数和对象个数
	unsigned int     objsize;//最小可用块或是固定对象结构大小
	//unsigned int     used_count;        
	//unsigned int     unused_count;        
	char             *name;//pool名
	pthread_spinlock_t lock;
}mem_pool_o;

// ****************************************************************************
mem_pool_o *mem_p_obj_create(int objsize, int objcount, int inc, char *name);
void mem_p_obj_destroy(mem_pool_o *mem_pool);


void *mem_p_obj_malloc(mem_pool_o *mem_pool, int size);
//void *mem_p_obj_calloc(mem_pool_o *mem_pool, unsigned int num);
void mem_p_obj_free(void *ptr);


void *mem_p_obj_malloc_safe(mem_pool_o *mem_pool, int size);
//void *mem_p_obj_calloc_safe(mem_pool_o *mem_pool, unsigned int num);
void mem_p_obj_free_safe(void *ptr);


#ifdef __cplusplus
}
#endif  // cplusplus 

#endif  //  

// ****************************************************************************

mem_pool.c

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#include "mem_pool.h"

typedef struct mem_pool_list
{
	struct list_head list;//池连
	struct list_head order_head;//回收连头
}mem_pool_l;
typedef struct mem_node_head
{
	mem_pool_o *mem_pool_h;//池头
	mem_pool_l *mem_pool_l;//池buff头
	struct list_head order_list;//回收连
	struct list_head size_list;//可用分配连
	int size;//可用大小
	int used;//使用状态
}mem_node_h;

typedef struct mem_unused_hash_
{
	struct list_head unused_head;
	int count;
}mem_unused_hash;

#define MEM_BLC_HEAD_OFFSET (sizeof(mem_pool_l))
#define MEM_OBJ_HEAD_OFFSET (sizeof(mem_node_h))

#define MEM_OBJ_HEAD_GET(ptr) ((mem_node_h *)((void *)ptr-MEM_OBJ_HEAD_OFFSET))

enum 
{
	USED,
	UNUSED,
};

inline void MEM_OBJ_USED_HASH_LIST_INIT(mem_pool_l *pool_buff_h, mem_pool_o *mem_pool_h)
{
	mem_node_h *ptr=NULL;
	
	int objcount= mem_pool_h->objcount;
	int objsize = mem_pool_h->objsize;
	ptr = (mem_node_h *)((void *)pool_buff_h + MEM_BLC_HEAD_OFFSET);

	ptr->mem_pool_h = mem_pool_h;
	ptr->mem_pool_l = pool_buff_h;

	ptr->size = objcount*(objsize + MEM_OBJ_HEAD_OFFSET) - MEM_OBJ_HEAD_OFFSET;
	ptr->used = UNUSED;
	mem_unused_hash *unused_hash=(mem_unused_hash *)mem_pool_h->unused_hash;

	list_add_tail(&ptr->size_list, &unused_hash[objcount-1].unused_head);
	unused_hash[objcount-1].count++;

	list_add_tail(&ptr->order_list, &pool_buff_h->order_head);
	return ;
}



/*
return: pool buff ptr
*/
void *mem_p_show_list(mem_pool_o *mem_pool)
{
	mem_node_h *node=NULL;	
	mem_node_h *tem;

	mem_unused_hash *hash_index=(mem_unused_hash *)mem_pool->unused_hash;

	int i;
	for(i=0; i<mem_pool->objcount; i++)
	{
		if(hash_index[i].count == 0){
			continue;
		}
		printf("id:%d c:%d | ",i, hash_index[i].count);
		list_for_each_entry_safe(node, tem, &hash_index[i].unused_head, size_list){
			printf("[%p %d %d] ", node , node->size, node->used);
		}
		printf("\n");
	}

	mem_pool_l *p_node=NULL;
	mem_pool_l *tem_node=NULL;

	
	list_for_each_entry_safe(p_node, tem_node, &mem_pool->pool_list, list){
		printf("order %p | ", p_node);
		list_for_each_entry_safe(node, tem, &p_node->order_head, order_list){
			printf("[%p %d %d] ", node , node->size, node->used);
		}
		printf("\n");
	}
	return NULL;
	p_node = node->mem_pool_l;
	list_for_each_entry_safe(node, tem, &p_node->order_head, order_list){
		printf("[%p %d %d] ", node , node->size, node->used);
	}
	printf("\n");
	return NULL;
}

/*
return: pool buff ptr
*/
mem_pool_l *mem_p_blc_calloc_get_buff(mem_pool_o *mem_pool, unsigned int objcount)
{
	void *buff=NULL;
	mem_pool_l *newpool=NULL;
	int block_size;
	if(objcount == 0){
		block_size = mem_pool->objcount*(mem_pool->objsize + MEM_OBJ_HEAD_OFFSET) + MEM_BLC_HEAD_OFFSET;
	}else{
		block_size = objcount*(mem_pool->objsize + MEM_OBJ_HEAD_OFFSET) + MEM_BLC_HEAD_OFFSET;
	}

	buff = calloc(1, block_size);
	if(buff == NULL){
		return NULL;
	}
	newpool = (mem_pool_l *)buff;
	
	INIT_LIST_HEAD(&newpool->order_head);
	list_add_tail(&newpool->list, &mem_pool->pool_list);
	return newpool;
}

/*
	mem_p_obj*  是基于对象结构的api
*/
mem_pool_o *mem_p_obj_create(int objsize, int objcount, int inc, char *name)
{
	int i;
	mem_pool_o *mem_pool=NULL;
	if(objsize<=0 || objcount<=0 || name == NULL){
		return NULL;
	}
	mem_pool = (mem_pool_o *)calloc(1, sizeof(mem_pool_o));
	if(mem_pool == NULL){
		return NULL;
	}
	mem_pool->inc_count = inc;
	mem_pool->objsize = objsize;
	//mem_pool->unused_count = objcount;
	//mem_pool->used_count = 0;
	mem_pool->objcount = objcount;
	INIT_LIST_HEAD(&mem_pool->pool_list);

	mem_pool->unused_hash=(void *)malloc(sizeof(mem_unused_hash)*(objcount+1));
	mem_unused_hash *unused_hash=(mem_unused_hash *)mem_pool->unused_hash;
	for(i=0; i<objcount; i++){
		INIT_LIST_HEAD(&unused_hash[i].unused_head);
		unused_hash[i].count=0;
	}
	pthread_spin_init(&mem_pool->lock, PTHREAD_PROCESS_PRIVATE);
	mem_pool->name = strdup(name);
	if(mem_pool->name == NULL){
		printf("mem pool name error\n");
		mem_p_obj_destroy(mem_pool);
		return NULL;
	}
	mem_pool_l *pool_buff = mem_p_blc_calloc_get_buff(mem_pool, 0);
	if(pool_buff == NULL){
		printf("mem pool name error\n");
		mem_p_obj_destroy(mem_pool);
		return NULL;
	}

	MEM_OBJ_USED_HASH_LIST_INIT(pool_buff, mem_pool);

	return mem_pool;
}
/*
	最好是在所以malloc free 之后再执行
*/
void mem_p_obj_destroy(mem_pool_o *mem_pool)
{
	mem_pool_l *node;
	mem_pool_l *tem_node;
	if(mem_pool == NULL){
		return ;
	}
	if(mem_pool->name!=NULL){
		free(mem_pool->name);
	}
	if(mem_pool->unused_hash!=NULL){
		free(mem_pool->unused_hash);
	}

	list_for_each_entry_safe(node, tem_node, &mem_pool->pool_list, list){
		list_del(&node->list);
		free(node);
	}
	
    pthread_spin_destroy(&mem_pool->lock);
	free(mem_pool);
	return ;
}

static int mem_p_obj_realloc(mem_pool_o *mem_pool)
{
	mem_pool_l *pool_buff = mem_p_blc_calloc_get_buff(mem_pool, 0);
	if(pool_buff == NULL){
		return -1;
	}

	MEM_OBJ_USED_HASH_LIST_INIT(pool_buff, mem_pool);
	return 0;
}
static inline void *mem_p_obj_malloc_from_list(mem_unused_hash *hash_head, int size)
{
	mem_node_h *node=NULL;
	mem_node_h *tem_node=NULL;
	int objcount;
	int objsize;
	int node_size;
	if(hash_head->count == 0){
		return NULL;
	}
	node = list_entry(hash_head->unused_head.next, typeof(*node), size_list);
	list_del(&node->size_list);
	hash_head->count--;

	
	objcount= node->mem_pool_h->objcount;
	objsize = node->mem_pool_h->objsize;
	/*
	list_for_each_entry_safe(node, tem_node, &hash_head->unused_head, size_list){
		list_del(&node->size_list);
		hash_head->count--;
		break;
	}
	*/
	node_size=node->size;

	if(node == NULL) return NULL;
	node->used = USED;
	if(node_size-size >= objsize + MEM_OBJ_HEAD_OFFSET){
		tem_node = (mem_node_h *)((void *)node + MEM_OBJ_HEAD_OFFSET + size);
		tem_node->mem_pool_h = node->mem_pool_h;
		tem_node->mem_pool_l = node->mem_pool_l;
		tem_node->used = UNUSED;
		tem_node->size = node_size-size - MEM_OBJ_HEAD_OFFSET;
		
		list_add_head(&tem_node->order_list,&node->order_list);
		
		int hash_index = (node_size-size - MEM_OBJ_HEAD_OFFSET)/objsize;
		//防止下标超界
		if(hash_index >= objcount)hash_index=objcount-1;
		mem_unused_hash *unused_hash=(mem_unused_hash *)node->mem_pool_h->unused_hash;
		list_add_tail(&tem_node->size_list, &unused_hash[hash_index].unused_head);
		unused_hash[hash_index].count++;
	}
	node->size = size;

	return (void *)node+MEM_OBJ_HEAD_OFFSET;
}
void *mem_p_obj_malloc(mem_pool_o *mem_pool, int size)
{
	void *node=NULL;
	int hash_index = size/mem_pool->objsize;
	int objcount = mem_pool->objcount;
	mem_unused_hash *unused_hash=(mem_unused_hash *)mem_pool->unused_hash;
	int k=0;

	if(unused_hash[hash_index].count != 0){
realloc:
		node = mem_p_obj_malloc_from_list(&unused_hash[hash_index], size);
		if(node != NULL){
			goto ret;
		}
	}
	
	int i;
	for(i= hash_index+1; i<objcount; i++){
		if(unused_hash[i].count == 0)continue;
		node = mem_p_obj_malloc_from_list(&unused_hash[i], size);
		if(node != NULL){
			goto ret;
		}
	}
	
	if(i == objcount && k==0){
		k=1;
		if(mem_p_obj_realloc(mem_pool)){
			return NULL;
		}
		hash_index = objcount-1;
		goto realloc;
	}
ret:
	return node;
}

static inline void mem_p_obj_del_from_order_list(mem_node_h *ptr_h)
{
	list_del(&ptr_h->size_list);
	return ;
}

static inline void mem_p_obj_del_from_size_list(mem_node_h *ptr_h)
{
	mem_pool_o *mem_pool=ptr_h->mem_pool_h;
	mem_unused_hash *unused_hash=(mem_unused_hash *)mem_pool->unused_hash;
	list_del(&ptr_h->size_list);
	unused_hash[ptr_h->size/mem_pool->objsize].count--;
	return ;
}
static inline void mem_p_obj_del_from_size_and_order_list(mem_node_h *ptr_h)
{
	mem_p_obj_del_from_size_list(ptr_h);
	list_del(&ptr_h->order_list);
	return ;
}
static inline void mem_p_obj_add_to_size_list(mem_node_h *ptr_h)
{
	mem_pool_o *mem_pool=ptr_h->mem_pool_h;
	int hash_index;
	int objcount= mem_pool->objcount;
	int objsize = mem_pool->objsize;
	mem_unused_hash *unused_hash=(mem_unused_hash *)mem_pool->unused_hash;
	ptr_h->used = UNUSED;
	hash_index = ptr_h->size/objsize;
	//防止下标超界
	if(hash_index >= objcount)hash_index=objcount-1;
	list_add_tail(&ptr_h->size_list, &unused_hash[hash_index].unused_head);
	unused_hash[hash_index].count++;
	return ;
}

void mem_p_obj_free(void *ptr)
{
	if(ptr == NULL){
		return ;
	}
	mem_node_h *ptr_h = MEM_OBJ_HEAD_GET(ptr);
	mem_node_h *pnode=NULL;
	mem_node_h *nnode=NULL;
	mem_node_h *tem_node;

	if(ptr_h->order_list.prev != &ptr_h->mem_pool_l->order_head){
		pnode = list_entry(ptr_h->order_list.prev, typeof(*pnode), order_list);
		/*
		list_for_each_exit_safe(pnode, tem_node, &ptr_h->order_list, order_list){
			break;
		}
	*/

	}
	if(ptr_h->order_list.next != &ptr_h->mem_pool_l->order_head){
		nnode = list_entry(ptr_h->order_list.next, typeof(*nnode), order_list);
		/*
		list_for_each_entry_safe(nnode, tem_node, &ptr_h->order_list, order_list){
			break;
		}
	*/
	}
	if(pnode == NULL && nnode->used == USED){
		//printf("1\n");
		mem_p_obj_add_to_size_list(ptr_h);
	}else if(pnode == NULL && nnode->used == UNUSED){
		//printf("2\n");
		ptr_h->size += nnode->size+MEM_OBJ_HEAD_OFFSET;
		mem_p_obj_add_to_size_list(ptr_h);
		mem_p_obj_del_from_size_and_order_list(nnode);
		
	}else if(nnode == NULL && pnode->used == USED){
		//printf("3\n");
		mem_p_obj_add_to_size_list(ptr_h);
	}else if(nnode == NULL && pnode->used == UNUSED){
		//printf("4\n");
		ptr_h->size += pnode->size+MEM_OBJ_HEAD_OFFSET;
		mem_p_obj_add_to_size_list(ptr_h);
		mem_p_obj_del_from_size_and_order_list(pnode);
	}else if(pnode->used == USED && nnode->used == USED){
		//printf("5\n");
		mem_p_obj_add_to_size_list(ptr_h);
	}else if(pnode->used == USED && nnode->used == UNUSED){
		//printf("6\n");
		ptr_h->size += nnode->size+MEM_OBJ_HEAD_OFFSET;
		mem_p_obj_add_to_size_list(ptr_h);
		mem_p_obj_del_from_size_and_order_list(nnode);
	}else if(pnode->used == UNUSED && nnode->used == USED){
		//printf("7\n");
		mem_p_obj_del_from_size_list(pnode);
		pnode->size += ptr_h->size+MEM_OBJ_HEAD_OFFSET;
		mem_p_obj_add_to_size_list(pnode);
		mem_p_obj_del_from_order_list(ptr_h);
	}else if(pnode->used == UNUSED && nnode->used == UNUSED){
		//printf("8\n");
		mem_p_obj_del_from_size_and_order_list(nnode);
		mem_p_obj_add_to_size_list(pnode);
		pnode->size += ptr_h->size+MEM_OBJ_HEAD_OFFSET+nnode->size+MEM_OBJ_HEAD_OFFSET;
		mem_p_obj_add_to_size_list(pnode);
		mem_p_obj_del_from_order_list(ptr_h);
	}

	return ;

}


void *mem_p_obj_malloc_safe(mem_pool_o *mem_pool, int size)
{
	void *res=NULL;
	pthread_spin_lock(&mem_pool->lock);
	res = mem_p_obj_malloc(mem_pool, size);
	pthread_spin_unlock(&mem_pool->lock);
	return res;
}
void mem_p_obj_free_safe(void *ptr)
{
	mem_node_h *ptr_h = MEM_OBJ_HEAD_GET(ptr);
	mem_pool_o *mem_pool=ptr_h->mem_pool_h;
	pthread_spin_lock(&mem_pool->lock);
	mem_p_obj_free(ptr);
	pthread_spin_unlock(&mem_pool->lock);
	return ;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brickie-liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值