swig/Source/DOH/Doh/memory.c
Dave Beazley 155cfdc73a *** empty log message ***
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@19 626c5289-ae23-0410-ae9c-e8d60b6d4f22
1999-08-18 21:40:29 +00:00

272 lines
7.3 KiB
C

/****************************************************************************
* DOH (Dynamic Object Hack)
*
* Author : David Beazley
*
* Department of Computer Science
* University of Chicago
* 1100 E 58th Street
* Chicago, IL 60637
* beazley@cs.uchicago.edu
*
* Please read the file LICENSE for the copyright and terms by which SWIG
* can be used and distributed.
****************************************************************************/
#include "doh.h"
#ifndef DOH_POOL_SIZE
#define DOH_POOL_SIZE 65536
#endif
#ifndef DOH_MAX_FRAG
#define DOH_MAX_FRAG 1024
#endif
static int _DohMemoryCurrent = 0;
static int _DohMemoryHigh = 0;
static int _PoolSize = DOH_POOL_SIZE;
/* -----------------------------------------------------------------------------
* memory.c
*
* Doh memory manager. Keeps pools of memory around for allocating objects.
* Pools are used to determine if an object is really a Doh object or not.
* ----------------------------------------------------------------------------- */
typedef struct fragment {
char *ptr; /* Pointer to fragment */
int len; /* Length of fragment */
struct fragment *next; /* Next fragment */
} Fragment;
static Fragment *FreeFragments[DOH_MAX_FRAG];
typedef struct pool {
char *ptr; /* Start of pool */
int len; /* Length of pool */
int current; /* Current position for next allocation */
struct pool *next; /* Next pool */
} Pool;
static Pool *Pools = 0;
static int pools_initialized = 0;
/* ----------------------------------------------------------------------
* Pool *CreatePool(int size)
*
* Create a new pool
* ---------------------------------------------------------------------- */
Pool *CreatePool(int size)
{
Pool *p = 0;
char *c;
c = (char *) DohMalloc(size);
if (!c) return 0;
p = (Pool *) DohMalloc(sizeof(Pool));
p->ptr = c;
p->len = size;
p->current = 0;
p->next = 0;
return p;
}
/* ----------------------------------------------------------------------
* void InitPools()
*
* Initialize the memory allocator
* ---------------------------------------------------------------------- */
static void InitPools() {
int i;
if (pools_initialized) return;
for (i = 0; i < DOH_MAX_FRAG; i++) {
FreeFragments[i] = 0;
}
Pools = CreatePool(_PoolSize); /* Create initial pool */
pools_initialized = 1;
}
/* ----------------------------------------------------------------------
* int DohCheck(DOH *ptr)
*
* Check if ptr is an object we created.
* ---------------------------------------------------------------------- */
int DohCheck(DOH *ptr) {
Pool *p = Pools;
char *cptr = (char *) ptr;
while (p) {
if ((cptr >= p->ptr) && (cptr < p->ptr+p->current)) return 1;
p = p->next;
}
return 0;
}
/* ----------------------------------------------------------------------
* int DohObjFreeCheck(DOH *ptr)
*
* Check if ptr is an object that has been deleted.
* ---------------------------------------------------------------------- */
int DohObjFreeCheck(DOH *ptr) {
int i;
Fragment *f;
char *cptr = (char *) ptr;
for (i = 0; i < DOH_MAX_FRAG; i++) {
f = FreeFragments[i];
while (f) {
if (f->ptr == cptr) return 1;
f = f->next;
}
}
return 0;
}
/* ----------------------------------------------------------------------
* void *DohObjMalloc(size_t size)
*
* Allocate an object
* ---------------------------------------------------------------------- */
void *DohObjMalloc(size_t size) {
Pool *p;
Fragment *f;
void *ptr;
if (size > DOH_MAX_FRAG) return 0;
if (!pools_initialized) InitPools();
p = Pools;
f = FreeFragments[size];
if (f) {
ptr = (void *) f->ptr;
FreeFragments[size] = f->next;
DohFree(f);
return ptr;
}
/* No free fragments. See if the pool is large enough */
if (size < (p->len - p->current)) {
ptr = (void *) (p->ptr + p->current);
p->current = (p->current + size + 7) & ~0x3;
return ptr;
}
/* Pool is not large enough. Create a new pool */
if (p->len - p->current > 0) {
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (p->ptr + p->current);
f->len = (p->len - p->current);
f->next = FreeFragments[f->len];
FreeFragments[f->len] = f;
}
p = CreatePool(_PoolSize);
p->next = Pools;
Pools = p;
return DohObjMalloc(size);
}
/* ----------------------------------------------------------------------
* void DohObjFree(DOH *ptr)
*
* Free a DOH object. Important! It must be a properly allocated
* DOH object. Not something else.
* ---------------------------------------------------------------------- */
void DohObjFree(DOH *ptr) {
DohBase *b;
Fragment *f;
extern int doh_debug_level;
if (!DohCheck(ptr)) {
DohError(DOH_MEMORY,"DohObjFree. %x not a DOH object!\n", ptr);
return; /* Oh well. Guess we're leaky */
}
b = (DohBase *) ptr;
if (!b->objinfo) {
DohError(DOH_MEMORY,"DohObjFree. %x not properly defined. No objinfo structure.\n", ptr);
return; /* Improperly initialized object. leak some more */
}
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (char *) ptr;
f->len = b->objinfo->objsize;
f->next = FreeFragments[f->len];
FreeFragments[f->len] = f;
}
/* -----------------------------------------------------------------------------
* void *DohMalloc(size_t nbytes)
*
* Wrapper around malloc() function. Records memory usage.
* ----------------------------------------------------------------------------- */
void *DohMalloc(size_t nbytes) {
char *ptr;
ptr = (char *) malloc(nbytes+8);
if (!ptr) return 0;
_DohMemoryCurrent += (nbytes+8);
if (_DohMemoryCurrent > _DohMemoryHigh) _DohMemoryHigh = _DohMemoryCurrent;
*((int *) ptr) = nbytes;
return (void *) (ptr+8);
}
/* -----------------------------------------------------------------------------
* void *DohRealloc(void *ptr, size_t newsize)
*
* Wrapper around realloc() function.
* ----------------------------------------------------------------------------- */
void *DohRealloc(void *ptr, size_t newsize) {
char *cptr = (char *) ptr;
char *nptr;
int size;
size = *((int *) (cptr - 8));
nptr = (char *) realloc(cptr-8,newsize+8);
if (!nptr) return 0;
*((int *) nptr) = newsize;
_DohMemoryCurrent += (newsize - size);
if (_DohMemoryCurrent > _DohMemoryHigh) _DohMemoryHigh = _DohMemoryCurrent;
return (void *) (nptr+8);
}
/* -----------------------------------------------------------------------------
* void DohFree(void *ptr)
*
* Wrapper around free() function. Records memory usage.
* ----------------------------------------------------------------------------- */
void DohFree(void *ptr) {
char *cptr = (char *) ptr;
int size;
size = *((int *) (cptr - 8));
free(cptr-8);
_DohMemoryCurrent -= (size+8);
}
/* -----------------------------------------------------------------------------
* int DohMemoryUse()
*
* Return bytes currently in use by Doh
* ----------------------------------------------------------------------------- */
int DohMemoryUse() {
return _DohMemoryCurrent;
}
int DohMemoryHigh() {
return _DohMemoryHigh;
}
int DohPoolSize(int poolsize) {
int ps;
ps = _PoolSize;
if (poolsize > 0) {
_PoolSize = poolsize;
}
return ps;
}