Switched to growable (unlimited) persistent objects / static references

repositories. Has been tested with 15K objects and appears to work. Also
done some significant chnages to auxiliary modules in libpobj, and the
trivial test program (test-list).
This commit is contained in:
Gilad Arnold 2004-12-16 09:00:07 +00:00
parent e30aca6138
commit 6502569a02
7 changed files with 754 additions and 562 deletions

View file

@ -4,7 +4,7 @@
#include <stdio.h> #include <stdio.h>
/* FIXME: send that to the make system. */ /* FIXME: send that to the make system. */
#define HAVE_DEBUG /* #define HAVE_DEBUG */
#ifdef HAVE_DEBUG #ifdef HAVE_DEBUG
#define debug(format,...) \ #define debug(format,...) \

View file

@ -4,49 +4,72 @@
#include "xmem.h" #include "xmem.h"
/* Hash item. */
struct hash_item { struct hash_item {
struct hash_item *next; struct hash_item *next;
unsigned long key; unsigned long key;
unsigned long val; unsigned long val;
}; };
struct hash_table {
int bucket_max;
unsigned long bucket_mask;
struct hash_item **table;
};
void
hash_init (hash_table table, int nbuckexp) struct hash_table *
hash_new (int nbuckexp)
{ {
int bucket_max = (int) ((unsigned long) 1 << nbuckexp); int bucket_max = (int) ((unsigned long) 1 << nbuckexp);
unsigned long bucket_mask = (unsigned long) bucket_max - 1;
struct hash_table *h;
memset (table, 0, bucket_max * sizeof (struct hash_item *)); h = (struct hash_table *) XMALLOC (sizeof (struct hash_table));
if (h)
h->table =
(struct hash_item **) XMALLOC (sizeof (struct hash_item *) * bucket_max);
if (! (h && h->table)) {
if (h)
XFREE (h);
return NULL;
}
h->bucket_max = bucket_max;
h->bucket_mask = bucket_mask;
memset (h->table, 0, sizeof (struct hash_item *) * bucket_max);
return h;
} }
void void
hash_close (hash_table table, int nbuckexp) hash_free (struct hash_table *h)
{ {
int bucket_max = (int) ((unsigned long) 1 << nbuckexp); int bucket_max = h->bucket_max;
struct hash_item *bucket, *next; struct hash_item *bucket, *next;
int i; int i;
for (i = 0; i < bucket_max; i++) { for (i = 0; i < bucket_max; i++) {
for (bucket = table[i]; bucket; bucket = next) { for (bucket = h->table[i]; bucket; bucket = next) {
next = bucket->next; next = bucket->next;
XFREE (XMEM_HASH, bucket); XFREE (bucket);
} }
table[i] = NULL;
} }
XFREE (h->table);
XFREE (h);
} }
unsigned long unsigned long
hash_lookup (hash_table table, int nbuckexp, unsigned long key) hash_lookup (struct hash_table *h, unsigned long key)
{ {
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1)); unsigned long bucket_mask = h->bucket_mask;
int bucket_index = (int) (key & bucket_mask);
struct hash_item *bucket; struct hash_item *bucket;
unsigned long val; unsigned long val;
debug ("tracing bucket %d for key %lu (%p)", debug ("tracing bucket %d for key %lu (%p)",
bucket_index, key, (void *) key); bucket_index, key, (void *) key);
for (bucket = table[bucket_index]; bucket; bucket = bucket->next) for (bucket = h->table[bucket_index]; bucket; bucket = bucket->next)
if (bucket->key == key) { if (bucket->key == key) {
val = bucket->val; val = bucket->val;
debug ("found %lu->%lu (%p->%p)", debug ("found %lu->%lu (%p->%p)",
@ -60,33 +83,34 @@ hash_lookup (hash_table table, int nbuckexp, unsigned long key)
} }
void void
hash_insert (hash_table table, int nbuckexp, hash_insert (struct hash_table *h, unsigned long key, unsigned long val)
unsigned long key, unsigned long val)
{ {
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1)); unsigned long bucket_mask = h->bucket_mask;
int bucket_index = (int) (key & bucket_mask);
struct hash_item *new; struct hash_item *new;
debug ("inserting %lu->%lu (%p->%p) to bucket %d", debug ("inserting %lu->%lu (%p->%p) to bucket %d",
key, val, (void *) key, (void *) val, bucket_index); key, val, (void *) key, (void *) val, bucket_index);
new = (struct hash_item *) XMALLOC (XMEM_HASH, sizeof (struct hash_item)); new = (struct hash_item *) XMALLOC (sizeof (struct hash_item));
new->key = key; new->key = key;
new->val = val; new->val = val;
new->next = table[bucket_index]; new->next = h->table[bucket_index];
table[bucket_index] = new; h->table[bucket_index] = new;
} }
unsigned long unsigned long
hash_delete (hash_table table, int nbuckexp, unsigned long key) hash_delete (struct hash_table *h, unsigned long key)
{ {
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1)); unsigned long bucket_mask = h->bucket_mask;
int bucket_index = (int) (key & bucket_mask);
struct hash_item *bucket, *prev; struct hash_item *bucket, *prev;
unsigned long val; unsigned long val;
debug ("tracing bucket %d for key %lu (%p)", debug ("tracing bucket %d for key %lu (%p)",
bucket_index, key, (void *) key); bucket_index, key, (void *) key);
for (prev = NULL, bucket = table[bucket_index]; bucket; for (prev = NULL, bucket = h->table[bucket_index]; bucket;
prev = bucket, bucket = bucket->next) prev = bucket, bucket = bucket->next)
if (bucket->key == key) { if (bucket->key == key) {
val = bucket->val; val = bucket->val;
@ -96,9 +120,9 @@ hash_delete (hash_table table, int nbuckexp, unsigned long key)
if (prev) if (prev)
prev->next = bucket->next; prev->next = bucket->next;
else else
table[bucket_index] = bucket->next; h->table[bucket_index] = bucket->next;
XFREE (XMEM_HASH, bucket); XFREE (bucket);
return val; return val;
} }

View file

@ -1,18 +1,13 @@
#ifndef __HASH_H #ifndef __HASH_H
#define __HASH_H #define __HASH_H
struct hash_table;
/* Hash table type and declaration macro. */ struct hash_table *hash_new (int);
typedef struct hash_item **hash_table; void hash_free (struct hash_table *);
#define HASH_DECLARE(name,nbuckexp) struct hash_item *name[1 << nbuckexp] unsigned long hash_lookup (struct hash_table *, unsigned long);
void hash_insert (struct hash_table *, unsigned long, unsigned long);
unsigned long hash_delete (struct hash_table *, unsigned long);
/* Prototypes. */
void hash_init (hash_table, int);
void hash_close (hash_table, int);
unsigned long hash_lookup (hash_table, int, unsigned long);
void hash_insert (hash_table, int, unsigned long, unsigned long);
unsigned long hash_delete (hash_table, int, unsigned long);
#endif /* __HASH_H */ #endif /* __HASH_H */

File diff suppressed because it is too large Load diff

View file

@ -1,117 +1,79 @@
#include <stdlib.h> #include <stdlib.h>
#include "common.h"
#include "xmem.h"
struct xmem { #define member_sizeof(s,x) (sizeof(((s *)NULL)->x))
#define member_offset(s,x) ((int)&(((s *)NULL)->x))
#ifdef HAVE_XMEM_DETAIL #ifdef HAVE_XMEM_DETAIL
/* Extended memory block info. */ struct xmem {
int mtype;
char *file; char *file;
int line; int line;
int size; int size;
struct xmem *prev; int dummy; /* dummy field to infer alignment. */
struct xmem *next;
#endif /* HAVE_XMEM_DETAIL */
/* Dummy field used to infer alignment. */
int dummy;
}; };
#define XMEM_OFFSET member_offset (struct xmem, dummy) # define XMEM_OFFSET member_offset (struct xmem, dummy)
#ifdef HAVE_XMEM
struct xmem_stat {
unsigned long count;
#ifdef HAVE_XMEM_DETAIL
unsigned long size;
struct xmem *head;
struct xmem *tail;
#endif /* HAVE_XMEM_DETAIL */ #endif /* HAVE_XMEM_DETAIL */
} xmem_stats[XMEM_MAX] = { { 0 } };
#endif /* HAVE_XMEM */
/* Default memory calls. */ /* Default memory calls. */
void *(*g_memfunc_malloc) (size_t) = malloc; void *(*g_memfunc_malloc) (size_t) = malloc;
void *(*g_memfunc_realloc) (void *, size_t) = realloc;
void (*g_memfunc_free) (void *) = free; void (*g_memfunc_free) (void *) = free;
#ifdef HAVE_XMEM_DETAIL
void * void *
xmem_malloc (int mtype, char *file, int line, size_t size) xmem_malloc (char *file, int line, size_t size)
{ {
struct xmem *x; struct xmem *x;
x = (struct xmem *) g_memfunc_malloc (size + XMEM_OFFSET); x = (struct xmem *) g_memfunc_malloc (size + XMEM_OFFSET);
if (! x) if (! x)
exit (1); return NULL;
x->file = file;
x->line = line;
x->size = size;
return (void *) ((char *) x + XMEM_OFFSET);
}
void *
xmem_realloc (char *file, int line, void *p, size_t size)
{
struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
x = (struct xmem *) g_memfunc_realloc (x, size + XMEM_OFFSET);
if (! x)
return NULL;
#ifdef HAVE_XMEM_DETAIL
/* Update object's extended info. */
x->mtype = mtype;
x->file = file; x->file = file;
x->line = line; x->line = line;
x->size = size; x->size = size;
/* Attach to object type list. */ return (void *) ((char *) x + XMEM_OFFSET);
x->next = NULL;
x->prev = xmem_stats[mtype].tail;
if (xmem_stats[mtype].tail)
xmem_stats[mtype].tail->next = x;
xmem_stats[mtype].tail = x;
if (! xmem_stats[mtype].head)
xmem_stats[mtype].head = x;
/* Update accumulated object sizes. */
xmem_stats[mtype].size += (unsigned long) size;
#endif /* HAVE_XMEM_DETAIL */
#ifdef HAVE_XMEM
/* Update accumulated type counter. */
xmem_stats[mtype].count++;
#endif /* HAVE_XMEM */
return (void *) (((char *) x) + XMEM_OFFSET);
} }
void void
xmem_free (int mtype, void *p) xmem_free (void *p)
{ {
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET); struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
#ifdef HAVE_XMEM_DETAIL
/* Verify object type consistency. */
if (mtype == XMEM_MAX)
mtype = x->mtype;
else if (mtype != x->mtype)
exit (1);
/* Detach from type list. */
if (x->prev)
x->prev->next = x->next;
else
xmem_stats[mtype].head = x->next;
if (x->next)
x->next->prev = x->prev;
else
xmem_stats[mtype].tail = x->prev;
/* Update accumulated object sizes. */
xmem_stats[mtype].size -= (unsigned long) x->size;
#endif /* HAVE_XMEM_DETAIL */
#ifdef HAVE_XMEM
/* Update accumulated type counter. */
xmem_stats[mtype].count--;
#endif /* HAVE_XMEM */
g_memfunc_free (x); g_memfunc_free (x);
} }
#endif /* HAVE_XMEM_DETAIL */
int int
xmem_memfunc (void *(*memfunc_malloc)(size_t), void (*memfunc_free)(void *)) xmem_memfunc (void *(*memfunc_malloc) (size_t),
void *(*memfunc_realloc) (void *, size_t),
void (*memfunc_free) (void *))
{ {
if (memfunc_malloc) if (memfunc_malloc)
g_memfunc_malloc = memfunc_malloc; g_memfunc_malloc = memfunc_malloc;
if (memfunc_realloc)
g_memfunc_realloc = memfunc_realloc;
if (memfunc_free) if (memfunc_free)
g_memfunc_free = memfunc_free; g_memfunc_free = memfunc_free;
@ -119,22 +81,11 @@ xmem_memfunc (void *(*memfunc_malloc)(size_t), void (*memfunc_free)(void *))
} }
int
xmem_obj_mtype (void *p)
{
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
return x->mtype;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
char * char *
xmem_obj_file (void *p) xmem_get_file (void *p)
{ {
#ifdef HAVE_XMEM_DETAIL #ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET); struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
return x->file; return x->file;
#else #else
return NULL; return NULL;
@ -142,10 +93,10 @@ xmem_obj_file (void *p)
} }
int int
xmem_obj_line (void *p) xmem_get_line (void *p)
{ {
#ifdef HAVE_XMEM_DETAIL #ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET); struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
return x->line; return x->line;
#else #else
return 0; return 0;
@ -153,49 +104,12 @@ xmem_obj_line (void *p)
} }
size_t size_t
xmem_obj_size (void *p) xmem_get_size (void *p)
{ {
#ifdef HAVE_XMEM_DETAIL #ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET); struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
return x->size; return x->size;
#else #else
return 0; return 0;
#endif /* HAVE_XMEM_DETAIL */ #endif /* HAVE_XMEM_DETAIL */
} }
unsigned long
xmem_stat_count (int mtype)
{
#ifdef HAVE_XMEM
return xmem_stats[mtype].count;
#else
return 0;
#endif /* HAVE_XMEM */
}
unsigned long
xmem_stat_size (int mtype)
{
#ifdef HAVE_XMEM_DETAIL
return xmem_stats[mtype].size;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
unsigned long
xmem_stat_alloc_list (int mtype, void (*cb) (char *, int, size_t, void *))
{
unsigned long count = 0;
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = xmem_stats[mtype].head;
while (x) {
cb (x->file, x->line, x->size, ((char *) x) + XMEM_OFFSET);
count++;
x = x->next;
}
#endif /* HAVE_XMEM_DETAIL */
return count;
}

View file

@ -1,35 +1,26 @@
#ifndef __XMEM_H #ifndef __XMEM_H
#define __XMEM_H #define __XMEM_H
enum {
/* General purpose identifiers. */
XMEM_TMP = 0,
XMEM_STR,
/* Dedicated object identifiers. */
XMEM_POBJ,
XMEM_HASH,
/* Teminator (don't use). */
XMEM_MAX
};
#define XMALLOC(t,s) xmem_malloc (t, __FILE__, __LINE__, s)
#define XFREE(t,p) xmem_free (t, p)
#ifdef HAVE_XMEM_DETAIL #ifdef HAVE_XMEM_DETAIL
#define XFREE_ANY(p) xmem_free (XMEM_MAX, p) void *xmem_malloc (char *, int, size_t);
void *xmem_realloc (char *, int, void *, size_t);
void xmem_free (void *);
# define XMALLOC(s) xmem_malloc (__FILE__, __LINE__, s)
# define XREALLOC(p,s) xmem_malloc (__FILE__, __LINE__, p, s)
# define XFREE(p) xmem_free (p)
#else
extern void *(*g_memfunc_malloc) (size_t);
extern void *(*g_memfunc_realloc) (void *, size_t);
extern void (*g_memfunc_free) (void *);
# define XMALLOC(s) g_memfunc_malloc(s)
# define XREALLOC(p,s) g_memfunc_realloc(p,s)
# define XFREE(p) g_memfunc_free(p)
#endif /* HAVE_XMEM_DETAIL */ #endif /* HAVE_XMEM_DETAIL */
void *xmem_malloc (int, char *, int, size_t); int xmem_memfunc (void *(*) (size_t), void *(*) (void *, size_t), void (*) (void *));
void xmem_free (int, void *); char *xmem_get_file (void *);
int xmem_memfunc (void *(*) (size_t), void (*) (void *)); int xmem_get_line (void *);
int xmem_obj_mtype (void *); size_t xmem_get_size (void *);
char *xmem_obj_file (void *);
int xmem_obj_line (void *);
size_t xmem_obj_size (void *);
unsigned long xmem_stat_count (int);
unsigned long xmem_stat_size (int);
unsigned long xmem_stat_alloc_list (int, void (*cb) (char *, int, size_t, void *));
#endif /* __XMEM_H */ #endif /* __XMEM_H */

View file

@ -25,7 +25,7 @@ main (int argc, char **argv)
printf ("first-time init\n"); printf ("first-time init\n");
/* Build list. */ /* Build list. */
next = NULL; next = NULL;
for (i = 0; i < 10; i++) { for (i = 0; i < 15000; i++) {
pobj_start (); pobj_start ();
tmp = (struct item *) pobj_malloc (sizeof (struct item)); tmp = (struct item *) pobj_malloc (sizeof (struct item));
if (! tmp) { if (! tmp) {