// mem_pool.h #ifndef mem_pool_h #define mem_pool_h #pragma once #define ALIGN 512 #define MAX_BLOCK_SIZE 20 * 1024 #define BLOCK_LIST_NUM MAX_BLOCK_SIZE / ALIGN class mem_pool { CRITICAL_SECTION alloc_lock; union obj{ union obj* free_list_link; char client_data[1]; }; obj* free_list [BLOCK_LIST_NUM]; static inline size_t round_up(size_t bytes){ return (bytes + ALIGN - 1) & ~(ALIGN - 1); } static inline size_t free_list_index(size_t bytes){ return (bytes + ALIGN - 1) / ALIGN - 1; } char* start_free; char* end_free; size_t heap_size; char* chunk_alloc(size_t size, int& nobjs); void* refill(size_t n); public: mem_pool(void); ~mem_pool(void); void* allocate(size_t n); void deallocate(void* p, size_t n); inline size_t mem_size(){return heap_size;} }; #endif // mem_pool.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "mem_pool.h" mem_pool::mem_pool(void){ InitializeCriticalSection(&alloc_lock); heap_size = 0; start_free = 0; end_free = 0; memset(free_list, 0, sizeof(free_list)); } mem_pool::~mem_pool(void){ DeleteCriticalSection(&alloc_lock); } char* mem_pool::chunk_alloc(size_t size, int& nobjs){ char* result; size_t total_bytes = size * nobjs; size_t bytes_left = end_free - start_free; if(bytes_left >= total_bytes){ result = start_free; start_free += total_bytes; return result; } if(bytes_left >= size){ nobjs = bytes_left / size; total_bytes = size * nobjs; result = start_free; start_free += total_bytes; return result; } if(bytes_left > 0){ obj **my_free_list = free_list + free_list_index(bytes_left); ((obj*) start_free)->free_list_link = *my_free_list; *my_free_list = (obj*) start_free; } size_t bytes_to_get = 2 * total_bytes + round_up(heap_size >> 4); start_free = (char *) malloc(bytes_to_get); if(start_free != 0){ heap_size += bytes_to_get; end_free = start_free + bytes_to_get; return chunk_alloc(size, nobjs); } int i = free_list_index(size) + 1; obj **my_free_list, *p; for(; i < BLOCK_LIST_NUM; ++i){ my_free_list = free_list + i; p = *my_free_list; if(0 != 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 = 0; return 0; } void* mem_pool::refill(size_t n){ int nobjs = 20; char* chunk = chunk_alloc(n, nobjs); obj** my_free_list; obj* result; obj *current_obj, *next_obj; int i; if(1 == nobjs) return chunk; my_free_list = free_list + free_list_index(n); result = (obj *) chunk; -- nobjs; *my_free_list = next_obj = (obj *) (chunk + n); for(i = 1; ; ++ i){ current_obj = next_obj; next_obj = (obj *) ((char*) next_obj + n); if(nobjs == i){ current_obj->free_list_link = 0; break; } current_obj->free_list_link = next_obj; } return result; } void* mem_pool::allocate(size_t n){ obj** my_free_list; obj* result; if(n <= 0) return 0; if(n > MAX_BLOCK_SIZE) return malloc(n); EnterCriticalSection(&alloc_lock); try{ my_free_list = free_list + free_list_index(n); result = *my_free_list; if(result == 0){ result = (obj *) refill(round_up(n)); }else{ *my_free_list = result->free_list_link; } }catch(...){ result = 0; } LeaveCriticalSection(&alloc_lock); return result; } void mem_pool::deallocate(void* p, size_t n){ obj *q = (obj *)p; obj** my_free_list; if(n > MAX_BLOCK_SIZE){ free(p); return; } my_free_list = free_list + free_list_index(n); EnterCriticalSection(&alloc_lock); q->free_list_link = *my_free_list; *my_free_list = q; LeaveCriticalSection(&alloc_lock); }