实现长度不固定 ,可分配,可回收,
只用于学习,性能太差,
分配大小时查找使用的是链式,下个版本收为红黑树查找
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 ;
}