mono - dp_malloc.c
#include "dp_malloc.h"
#include <assert.h>
//===================================================================
//: setting
//===================================================================
#define MALLOC malloc
#define FREE free
//===================================================================
//: types
//===================================================================
typedef struct tListHead {
struct tListHead *next, *prev;
} ListHead;
#define mListInit(P) ((P)->prev=(P)->next=(P))
#define mListInsert(H,P) ((P)->next=(H)->next,(P)->prev=(H),(P)->prev->next=(P),(P)->next->prev=(P))
#define mListDelete(P) ((P)->next->prev=(P)->prev,(P)->prev->next=(P)->next)
//--------------------------------------------------------------
typedef struct tInfo {
struct tInfo *next, *prev;
void *ptr;
int size;
DP_Func del_func, final_proc;
ListHead child;
} Info;
static const int cHashSize[] = {
17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411, 32771, 65537,
};
typedef struct {
int max_index;
Info *info;
} Hash;
static Hash sDP;
//===================================================================
//: hash
//===================================================================
static void Resize(int new_size);
static int GetHash(void *p) {
return (int)p % cHashSize[sDP.max_index];
}
static Info *GetInfo(void *p) {
int no, i, max = cHashSize[sDP.max_index];
if(p) {
no = GetHash(p);
for(i=0; i<max; i++) {
if(sDP.info[no].ptr == p) return &sDP.info[no];
no = (no + 1) % max;
}
}
return 0;
}
static Info *GetUse(void *p) {
Info *info = GetInfo(p);
assert(p);
assert(info);
return info;
}
static Info *GetEmpty(void *p) {
int i, max = cHashSize[sDP.max_index];
int no = GetHash(p);
for(i=0; i<max; i++) {
assert(sDP.info[no].ptr != p);
if(sDP.info[no].ptr == 0)
return &sDP.info[no];
no = (no + 1) % max;
}
Resize(sDP.max_index+1);
return GetEmpty(p);
}
static void NewDP(int max_index) {
int i, max = cHashSize[max_index];
sDP.max_index = max_index;
sDP.info = MALLOC(sizeof(Info) * max);
for(i=0; i<max; i++) {
Info *info = &sDP.info[i];
info->ptr = info->del_func = info->final_proc = 0;
mListInit(info);
mListInit(&info->child);
}
}
static void Link(void *p, int size, DP_Func del_func, DP_Func final_proc, void *owner) {
Info *info = GetEmpty(p);
info->ptr = p;
info->size = size;
info->del_func = del_func;
info->final_proc = final_proc;
if(owner) {
Info *owner_info = GetUse(owner);
mListInsert((Info*)&owner_info->child, info);
} else {
mListInit(info);
}
}
static void UnLink(Info *info) {
mListDelete(info);
mListInit(info);
}
static void Remap(Info *info, void *owner) {
Link(info->ptr, info->size, info->del_func, info->final_proc, owner);
while(info->child.next != &info->child) Remap((void*)info->child.next, info->ptr);
mListDelete(info);
}
static void RemapAll(Hash *old) {
Info *info;
int i, max = cHashSize[old->max_index];
for(i=0; i<max; i++) {
info = &old->info[i];
if(info->ptr && info->prev == info && info->next == info)
Remap(info, 0);
}
}
static void Resize(int new_size) {
Hash old_hash = sDP;
NewDP(new_size);
RemapAll(&old_hash);
FREE(old_hash.info);
}
//===================================================================
//: malloc/free
//===================================================================
int DP_Check(void *p) {
return GetInfo(p) ? 1 : 0;
}
int DP_Size(void *p) {
if(p) {
Info *info = GetUse(p);
return info->size;
}
return 0;
}
void* DP_ChangeOwner(void *p, void *owner) {
Info *info = GetUse(p);
UnLink(info);
if(owner) {
Info *owner_info = GetUse(owner);
mListInsert((Info*)&owner_info->child, info);
}
return p;
}
void *DP_SetFinalize(void *p, DP_Func final_func) {
Info *info = GetUse(p);
info->final_proc = final_func;
return p;
}
void *DP_Link(void *p, DP_Func del_func, void *owner) {
Link(p, 0, del_func, 0, owner);
return p;
}
static void Free(void *p) {
FREE(p);
}
void *DP_Malloc(int size, void *owner) {
void *p = MALLOC(size);
assert(p);
Link(p, size, Free, 0, owner);
return p;
}
static void FreeInfo(Info *info) {
while(info->child.next != &info->child) {
FreeInfo((Info*)info->child.next);
}
if(info->final_proc) {
info->final_proc(info->ptr);
info->final_proc = 0;
}
if(info->del_func) {
info->del_func(info->ptr);
info->del_func = 0;
}
info->ptr = 0;
mListDelete(info);
}
void *DP_Free(void *p) {
if (p)
FreeInfo(GetUse(p));
return 0;
}
//===================================================================
//: control
//===================================================================
void DP_Quit(void) {
int i, max = cHashSize[sDP.max_index];
for(i=0; i<max; i++) DP_Free(sDP.info[i].ptr);
FREE(sDP.info);
}
void DP_Init(void) {
NewDP(7);
//atexit(DP_Quit);
}