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);
}

update
new
search

dp_malloc.h
dp_malloc.c
FrontPage
—^‘¾