/*
* mempool.c
*/
#include "EXTERN.h"
#include "common.h"
#include "final.h"
#include "util.h"
#include "util2.h"
#include "INTERN.h"
#include "mempool.h"
#include "mempool.ih"
/* any of these defines can be increased arbitrarily */
#define MAX_MEM_POOLS 16
#define MAX_MEM_FRAGS 4000
/* number of bytes in a fragment */
#define FRAG_SIZE ((1024*64)-32)
typedef struct mp_frag {
char* data;
char* lastfree;
long bytesfree;
int next;
} MP_FRAG;
/* structure for extensibility */
typedef struct mp_head {
int current; /* index into mp_frag of most recent alloc */
} MP_HEAD;
static MP_FRAG mpfrags[MAX_MEM_FRAGS]; /* zero is unused */
static int mp_first_free_frag;
static MP_HEAD mpheads[MAX_MEM_POOLS];
void
mp_init()
{
int i;
for (i = 1; i < MAX_MEM_FRAGS; i++) {
mpfrags[i].data = NULL;
mpfrags[i].lastfree = NULL;
mpfrags[i].bytesfree = 0;
mpfrags[i].next = i+1;
}
mpfrags[i-1].next = 0;
mp_first_free_frag = 1; /* first free fragment */
for (i = 0; i < MAX_MEM_POOLS; i++)
mpheads[i].current = 0;
}
/* returns the fragment number */
static int
mp_alloc_frag()
{
int f;
f = mp_first_free_frag;
if (f == 0) {
printf("trn: out of memory pool fragments!\n");
sig_catcher(0); /* die. */
}
mp_first_free_frag = mpfrags[f].next;
if (mpfrags[f].bytesfree)
return f; /* already allocated */
mpfrags[f].data = (char*)safemalloc(FRAG_SIZE);
mpfrags[f].lastfree = mpfrags[f].data;
mpfrags[f].bytesfree = FRAG_SIZE;
return f;
}
/* frees a fragment number */
static void
mp_free_frag(f)
int f;
{
#if 0
/* old code to actually free the blocks */
if (mpfrags[f].data)
free(mpfrags[f].data);
mpfrags[f].lastfree = NULL;
mpfrags[f].bytesfree = 0;
#else
/* instead of freeing it, reset it for later use */
mpfrags[f].lastfree = mpfrags[f].data;
mpfrags[f].bytesfree = FRAG_SIZE;
#endif
mpfrags[f].next = mp_first_free_frag;
mp_first_free_frag = f;
}
char*
mp_savestr(str,pool)
char* str;
int pool;
{
int f, oldf;
int len;
char* s;
if (!str) {
#if 1
printf("\ntrn: mp_savestr(NULL,%d) error.\n",pool);
assert(FALSE);
#else
return NULL; /* only a flesh wound... (;-) */
#endif
}
len = strlen(str);
if (len >= FRAG_SIZE) {
printf("trn: string too big (len = %d) for memory pool!\n",len);
printf("trn: (maximum length allowed is %d)\n",FRAG_SIZE);
sig_catcher(0); /* die. */
}
f = mpheads[pool].current;
/* just to be extra safe, keep 2 bytes unused at end of block */
if (f == 0 || len >= mpfrags[f].bytesfree-2) {
oldf = f;
f = mp_alloc_frag();
mpfrags[f].next = oldf;
mpheads[pool].current = f;
}
s = mpfrags[f].lastfree;
safecpy(s,str,len+1);
mpfrags[f].lastfree += len+1;
mpfrags[f].bytesfree -= len+1;
return s;
}
/* returns a pool-allocated string */
char*
mp_malloc(len,pool)
int len;
int pool;
{
int f,oldf;
char* s;
if (len == 0)
len = 1;
if (len >= FRAG_SIZE) {
printf("trn: malloc size too big (len = %d) for memory pool!\n",len);
printf("trn: (maximum length allowed is %d)\n",FRAG_SIZE);
sig_catcher(0); /* die. */
}
f = mpheads[pool].current;
if (f == 0 || len >= mpfrags[f].bytesfree) {
oldf = f;
f = mp_alloc_frag();
mpfrags[f].next = oldf;
mpheads[pool].current = f;
}
s = mpfrags[f].lastfree;
mpfrags[f].lastfree += len+1;
mpfrags[f].bytesfree -= len+1;
return s;
}
/* free a whole memory pool */
void
mp_free(pool)
int pool;
{
int oldnext;
int f;
f = mpheads[pool].current;
while (f) {
oldnext = mpfrags[f].next;
mp_free_frag(f);
f = oldnext;
}
mpheads[pool].current = 0;
}
syntax highlighted by Code2HTML, v. 0.9.1