参考SGI-STL实现的内存池头文件,代码不过一百来行,非常简单。
为了简化代码,做了如下改动:
- 取消错误处理(错误处理主要在内存申请失败上,现在电脑内存都很大,基本不存在申请不到内存的情况)
- 取消
remalloc
,只提供malloc
与free
两个接口
内存池源码:
#pragma once
#include<cstdlib>
class TAmempool {
private:
enum {UNIT=8};
enum {MAXSIZE=128};
enum {LISTLEN=MAXSIZE/UNIT};
union listnode {
union listnode* next;
char memaddr[1];
};
static listnode* volatile listheadarr[LISTLEN];
static char* end_free;
static char* start_free;
static size_t heap_size;
/*align the user's memunit size*/
static size_t round_up(size_t bytes) {
return (bytes + UNIT-1) & ~(UNIT - 1);//!!!!!
}
/*to get the position fo the mem block of this size*/
static size_t getlistindex(size_t bytes) {
return (bytes + UNIT - 1) / UNIT - 1;
}
static void* refill(size_t n) {
int nodenum = 20;
char* chunk = chunkalloc(n, nodenum);
if (nodenum == 1) {
return chunk;
}
listnode* volatile* listhead;
listnode* result;
listnode* current_node;
listnode* next_node;
listhead = listheadarr + getlistindex(n);
*listhead = next_node = (listnode*)(chunk + n);
//TODO:this loop needs to be simplyfy
//for (int i = 1;; i++) {
// current_node = next_node;
// next_node = (listnode*)((char*)next_node + n);
// if (nodenum - 1 == i) {
// current_node->next = 0;
// break;
// } else {
// current_node->next = next_node;
// }
//}
for (int i = 1; nodenum - 1 != i; i++) {
current_node = next_node;
next_node = (listnode*)((char*)next_node + n);
current_node->next = next_node;
}
current_node = next_node;
next_node = (listnode*)((char*)next_node + n);
current_node->next = 0;
return (listnode*)chunk;
}
static char* chunkalloc(size_t nodesize, int& nodenum) {
size_t total_bytes = nodesize * nodenum;
size_t bytes_left = end_free-start_free;
char* result;
//TODO:too complicated
if (bytes_left >= total_bytes) {
result = start_free;
start_free += total_bytes;
return result;
} else if (bytes_left >= nodesize) {
nodenum = bytes_left / nodesize;
total_bytes = nodesize * nodenum;
result = start_free;
start_free += total_bytes;
return result;//!!!!!
} else {
//将剩余的一点内存分配到最合适的地方去
size_t bytes_to_get = 2 * total_bytes + round_up(heap_size >> 4);
if (bytes_left > 0) {
listnode* volatile* listhead = listheadarr + getlistindex(bytes_left);
((listnode*)start_free)->next = *listhead;
*listhead = (listnode*)start_free;
}
//从系统申请新的内存
start_free = (char*)std::malloc(bytes_to_get);
end_free = start_free + bytes_to_get;
heap_size += bytes_to_get;
return chunkalloc(nodesize, nodenum);
}
}
public:
static void* malloc(size_t n) {
listnode* volatile* listhead;
listnode* result;
if (n > (size_t)MAXSIZE) {
return std::malloc(n);
}
listhead = listheadarr + getlistindex(n);
result = *listhead;
if (result == 0) {//? where the 0 come from?
return refill(round_up(n));
}
*listhead = result->next;
return result;
}
static void free(void *p,size_t n) {
listnode* q = (listnode*) p;
listnode* volatile* listhead;
if (n > (size_t)MAXSIZE) {
std::free(p);//为了不与本类中的free冲突
return;
}
listhead = listheadarr + getlistindex(n);
q->next = *listhead;
*listhead = q;
}
};
TAmempool::listnode* volatile TAmempool::listheadarr[LISTLEN] = { 0 };
char* TAmempool::end_free = 0;
char* TAmempool::start_free = 0;
size_t TAmempool::heap_size = 0;
测试源码:
#include<iostream>
#include "TAmempool.h"
using namespace std;
#include<ctime>
class TAtimer {
clock_t startTime;
clock_t endTime;
public:
void start() {
startTime = clock();
}
void stop() {
endTime = clock();
}
float getS() {
return float(endTime - startTime) / CLOCKS_PER_SEC;
}
clock_t get() {
return (endTime - startTime);
}
};
int main() {
TAmempool pool;
int** x;
int t=0;
x = new int* [10000];
TAtimer timer;
for (int m = 0; m < 10; m++) {
timer.start();
for (int j = 1; j < 200; j++) {
for (int i = 0; i < 10000; i++) {
//cout << i<<" ";
x[i] = (int*)pool.malloc(sizeof(int));
}
for (int i = 0; i < 10000; i++) {
pool.free(x[i], sizeof(int));
}
}
timer.stop();
cout << timer.get() << endl;
t += timer.get();
}
cout <<endl<< t /10;
return 0;
}