看完自己重写了一下,不知道的又看了一遍,里面没有考虑多线程的问题,主要是想实现以下内存池。
Mempool.h
#ifndef MEMPOOL_H_
#define MEMPOOL_H_
#include <cstddef>
#include <new>
#include <cstdlib>
namespace flysnow {
enum {STEP_ = 8};
enum {MAX_BYTES_ = 128};
enum {FREELIST_NUM_ = MAX_BYTES_/STEP_};
class Mempool{
private:
union pool_bucket {
union pool_bucket* next_node;
char bucket_addr[1];
};
static size_t up_to_nearest(size_t n) {
return STEP_*((n>>3) + (n%8 ? 1:0));
}
static size_t freelist_index(size_t n) {
return ((n>>3) + (n%8 ? 0:-1));
}
static void* refill(size_t n);
static char* alloc_memory(size_t size,int &pool_node_num);
static pool_bucket* free_list_[FREELIST_NUM_];
static char* start_pool;
static char* end_pool;
static size_t heap_size;
public:
static void* allocate(size_t n);
static void deallocate(void *p,size_t n);
static size_t get_heap_size() {return heap_size;}
};
}
#endif
Mempool.cpp
#include "mempool.h"
namespace flysnow{
char* Mempool::start_pool = 0;
char* Mempool::end_pool = 0;
size_t Mempool::heap_size = 0;
Mempool::pool_bucket* Mempool::free_list_[FREELIST_NUM_] =
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void* Mempool::allocate(size_t n) {
if(n > MAX_BYTES_){
return malloc(n);
}
pool_bucket *p;
pool_bucket **free_list_index = free_list_ + freelist_index(n);
p = *free_list_index;
if(0 == p) {
void *q = refill(up_to_nearest(n));
return q;
}
*free_list_index = p->next_node;
return p;
}
void Mempool::deallocate(void *p,size_t n) {
pool_bucket *q = (pool_bucket*)p;
if(n > MAX_BYTES_) {
free(p);
return ;
}
pool_bucket **free_list_index = free_list_ + freelist_index(n);
q->next_node = *free_list_index;
*free_list_index = q;
}
void* Mempool::refill(size_t n) {
int pool_node_num = 20;
int i;
pool_bucket **free_list_index = free_list_ + freelist_index(n);
char *pool = alloc_memory(n,pool_node_num);
if(1 == pool_node_num) {
return pool;
}
pool_bucket *result = (pool_bucket*)pool;
pool_bucket *current,*next;
pool += n;
*free_list_index = next = (pool_bucket*)pool;
next = (pool_bucket*)pool;
for(i=1; ;++i){
current = next;
next = (pool_bucket*)((char*)next + n);
if(pool_node_num - 1 == i){
current->next_node = NULL;
break;
} else {
current->next_node = next;
}
}
return result;
}
char* Mempool::alloc_memory(size_t size,int &pool_node_num) {
size_t total_size = size*pool_node_num;
size_t remain_size = end_pool - start_pool;
if(total_size <= remain_size) {
char* result = start_pool;
start_pool += total_size;
return result;
} else if(remain_size >= size) {
pool_node_num = remain_size/size;
size_t return_size = pool_node_num*size;
char *result = start_pool;
start_pool += return_size;
return result;
} else {
size_t get_size = 2*total_size + up_to_nearest(heap_size>>4);
if(remain_size > 0) {
//如果剩余7byte,此处会放在8byte的自由链表中,然而,最后allocate 8byte的
//时候,岂不会出错?
//原来之前get_size分配的内存总是8的倍数,因此不会出现以上情况。。。。
pool_bucket **free_list_index = free_list_ + freelist_index(remain_size);
((pool_bucket*)start_pool)->next_node = *free_list_index;
*free_list_index = (pool_bucket*)start_pool;
}
start_pool = (char*)malloc(get_size);
if(0 == start_pool) {
pool_bucket **free_list_index;
pool_bucket *p;
for(int i=size;i<=MAX_BYTES_;i+=STEP_) {
free_list_index = free_list_ + freelist_index(i);
p = *free_list_index;
if(0 != p) {
*free_list_index = p->next_node;
start_pool = (char*)p;
end_pool = start_pool + i;
return (alloc_memory(size,pool_node_num));
}
}
end_pool = 0;
start_pool = (char*)malloc(get_size);
}
heap_size += get_size;
end_pool = start_pool + get_size;
//return (alloc_memory(size,pool_node_num));
char *result = start_pool;
start_pool += total_size;
return result;
}
}
}
main.cpp
#include <iostream>
#include "mempool.h"
using namespace std;
int main()
{
char *p;
for(size_t i=0;i<100000;++i){
p = (char*)flysnow::Mempool::allocate(i%1029+1);
cout<<flysnow::Mempool::get_heap_size()<<' ';
}
cout << endl;
system("PAUSE");
return 0;
}