//mempool.h
#ifndef _MEM_POOL_H
#define _MEM_POOL_H
#include <stdlib.h>
static size_t __freelist_index(size_t bytes);
static size_t __round_up(size_t bytes);
static void mem_init();
static void* mem_malloc(size_t n);
static void mem_free(void* p,size_t n);
static void mem_destroy();
//static void *mem_realloc(void*ptr,size_t newsize,size_t oldsize);
static void *refill(size_t n);
static char *chunk_alloc(size_t size,int *nobjs);
#define __MAX_BYTES 20*1024
#define __ALIGN 512
#define __NFREELISTS __MAX_BYTES/__ALIGN
typedef union obj{
union obj *free_list_link;
char client_data[1];
}obj;
obj *free_list[__NFREELISTS];
static char* start_free;
static char* end_free;
static size_t heap_size;
static unsigned long g_addr[__NFREELISTS * 10];
static int g_addr_num=0;
#endif
//mempool.c
#include <stdio.h>
#include "string.h"
#include "mempool.h"
static size_t __freelist_index(size_t bytes) {
return (bytes + __ALIGN - 1) /__ALIGN - 1;
}
static size_t __round_up(size_t bytes){
return (bytes + __ALIGN - 1) & ~(__ALIGN-1);
}
static void *mem_malloc(size_t n) {
obj**my_free_list;
obj* result;
void *p;
if(n > (size_t)__MAX_BYTES) {
p = malloc(n);
return p;
}
my_free_list = free_list + __freelist_index(n);
result = *my_free_list;
if(result == NULL) {
p = refill(__round_up(n));
return p;
}
*my_free_list = result->free_list_link;
return result;
}
static void mem_free(void*p,size_t n){
obj* q = (obj*)p;
obj** my_free_list;
if(n > (size_t)__MAX_BYTES) {
free(p);
return ;
}
my_free_list = free_list + __freelist_index(n);
q->free_list_link = *my_free_list;
*my_free_list = q;
}
static void *refill(size_t n) {
int nobjs = 20;
char *chunk = chunk_alloc(n,&nobjs);
obj** my_free_list;
obj* result;
obj* curr_obj,*next_obj;
int i;
if(nobjs == 1) return chunk;
my_free_list = free_list + __freelist_index(n);
result = (obj*)chunk;
*my_free_list = next_obj = (obj*)(chunk + n);
for (i=1;i<nobjs;i++) {
curr_obj = next_obj;
next_obj = (obj*)((char*)next_obj + n);
curr_obj->free_list_link = next_obj;
}
curr_obj->free_list_link = NULL;
return result;
}
static char* chunk_alloc(size_t size,int *nobjs) {
char *result;
size_t total_bytes = size * (*nobjs);
size_t left_bytes = end_free - start_free;
size_t bytes_to_get;
obj **my_free_list,*p;
int i;
if(left_bytes >= total_bytes) {
result = start_free;
start_free += total_bytes;
return result;
}
if(left_bytes >= size) {
*nobjs = (int)(left_bytes/size);
total_bytes = size * (*nobjs);
result = start_free;
start_free += total_bytes;
return result;
}
if(left_bytes > 0) {
my_free_list = free_list + __freelist_index(left_bytes);
((obj*)start_free)->free_list_link = *my_free_list;
*my_free_list = (obj*)start_free;
}
bytes_to_get = 2*total_bytes + __round_up(heap_size >> 4);
start_free = (char*)malloc(bytes_to_get);
g_addr[g_addr_num ++] = start_free;
if(start_free) {
heap_size += bytes_to_get;
end_free = start_free + bytes_to_get;
return chunk_alloc(size,nobjs);
}
i = (int)__freelist_index(size) + 1;
for(;i<__NFREELISTS;++i) {
my_free_list = free_list + i;
p = *my_free_list;
if(p) {
*my_free_list = p->free_list_link;
start_free = (char*)p;
end_free = start_free+(i + 1) * __ALIGN;
return chunk_alloc(size,nobjs);
}
}
end_free = NULL;//应该抛出异常
return NULL;
}
static void mem_init() {
int i;
start_free = end_free = NULL;
heap_size = 0;
for(i=0;i<__NFREELISTS;free_list[i]=NULL,++i);
memset(g_addr,0,sizeof(g_addr));
g_addr_num = 0;
}
static void mem_destroy() {
int i;
for( i=0;i<g_addr_num;++i) {
free(g_addr[i]);
}
}