#include <stdio.h> #include <memory.h> #define PAGEINTSIZE 1024 #define PAGESIZE 4096 struct Page { char mm[PAGESIZE]; bool Initial(unsigned int size) { if((size & (size -1)) || (size & 3)) return false; memset(&mm, 0, sizeof(Page)); *((void**)(&mm[PAGESIZE - size])) = NULL; for(int i = sizeof(Page) / size - 2; i >= 0; i--) { *((void**)(&mm[i * size])) = &mm[i * size + size]; } return true; } }; struct Page_Desc { Page* pPage; void* pEmpty; Page_Desc* next; unsigned int refCount; unsigned int bucketSize; }; struct Bucket { unsigned int bucketSize; Page_Desc* first; }; static Bucket buckets[] = { //{4, NULL}, {8, NULL}, {16, NULL}, {32, NULL}, {64, NULL}, {128, NULL}, {256, NULL}, {512, NULL}, {1024, NULL}, {2048, NULL}, {4096, NULL}, {0, NULL} }; static int bucketCount = sizeof(buckets)/sizeof(Bucket); void* Malloc(unsigned int size) { if(size <= 0 || size > buckets[bucketCount - 2].bucketSize) throw "Invalid Memory Size"; for(int i = 0; i < bucketCount - 1; i++) { if(size > buckets[i].bucketSize) continue; //we reach the bucket buckets[i] Page_Desc* p = buckets[i].first; while(true) { if(p != NULL ) { if(p->refCount != sizeof(Page)/p->bucketSize) { //we find a empty position void* ret = p->pEmpty; p->pEmpty = *((void**)(p->pEmpty)); p->refCount++; return ret; } //we need find the next one p = p->next; } //if we got here, that's to say no page can supply the space, //we should malloc a new page, and add it to the beginning of the list Page* page = new Page(); page->Initial(buckets[i].bucketSize); Page_Desc* pageDesc = new Page_Desc(); pageDesc->bucketSize = buckets[i].bucketSize; pageDesc->pPage = page; pageDesc->pEmpty = *((void**)page); pageDesc->refCount = 1; //if it support the mutithreads, we should do //an atomic operation for folloeing teo steps pageDesc->next = buckets[i].first; buckets[i].first = pageDesc; return (void*)page; } } throw "Malloc Memory Error"; } void Free(void* addr) { //we first find which page the addr belong to for(int i = 0; i < bucketCount -1; i++) { Page_Desc* p = buckets[i].first; Page_Desc* q = NULL; while(p != NULL) { if(addr >= p->pPage && addr < p->pPage + sizeof(Page)) { //the addr is contained in this page. //but we still need check whether it is a valid addr if((*((long long*)&addr)- *((long long*)&p->pPage)) % p->bucketSize != 0) throw "Invalid Memory Address"; if(p->refCount == 1) { //we should free the page. if( q == NULL) buckets[i].first = p->next; else q->next = p->next; delete p->pPage; delete p; } else { p->refCount--; *((void**)addr) = p->pEmpty; p->pEmpty = addr; } return; } q = p; p = p->next; } } throw "Invalid Memory Address"; } int main() { int* a = (int*)Malloc(sizeof(int)); int* b = (int*)Malloc(sizeof(int)); int* c = (int*)Malloc(sizeof(int)); int* d = (int*)Malloc(sizeof(int)); *a = 5; *b = *c = *d = 0x12345678; Page_Desc* page = (Page_Desc*)Malloc(sizeof(Page_Desc)); page->refCount == 23; Free(a); Free(b); Free(c); Free(d); Free(page); return 0; }