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:
parent
e30aca6138
commit
6502569a02
7 changed files with 754 additions and 562 deletions
|
@ -4,7 +4,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
/* FIXME: send that to the make system. */
|
||||
#define HAVE_DEBUG
|
||||
/* #define HAVE_DEBUG */
|
||||
|
||||
#ifdef HAVE_DEBUG
|
||||
#define debug(format,...) \
|
||||
|
|
|
@ -4,49 +4,72 @@
|
|||
#include "xmem.h"
|
||||
|
||||
|
||||
/* Hash item. */
|
||||
struct hash_item {
|
||||
struct hash_item *next;
|
||||
unsigned long key;
|
||||
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);
|
||||
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
|
||||
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;
|
||||
int 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;
|
||||
XFREE (XMEM_HASH, bucket);
|
||||
XFREE (bucket);
|
||||
}
|
||||
table[i] = NULL;
|
||||
}
|
||||
XFREE (h->table);
|
||||
XFREE (h);
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned long val;
|
||||
|
||||
debug ("tracing bucket %d for key %lu (%p)",
|
||||
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) {
|
||||
val = bucket->val;
|
||||
debug ("found %lu->%lu (%p->%p)",
|
||||
|
@ -60,33 +83,34 @@ hash_lookup (hash_table table, int nbuckexp, unsigned long key)
|
|||
}
|
||||
|
||||
void
|
||||
hash_insert (hash_table table, int nbuckexp,
|
||||
unsigned long key, unsigned long val)
|
||||
hash_insert (struct hash_table *h, 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;
|
||||
|
||||
debug ("inserting %lu->%lu (%p->%p) to bucket %d",
|
||||
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->val = val;
|
||||
new->next = table[bucket_index];
|
||||
table[bucket_index] = new;
|
||||
new->next = h->table[bucket_index];
|
||||
h->table[bucket_index] = new;
|
||||
}
|
||||
|
||||
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;
|
||||
unsigned long val;
|
||||
|
||||
debug ("tracing bucket %d for key %lu (%p)",
|
||||
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)
|
||||
if (bucket->key == key) {
|
||||
val = bucket->val;
|
||||
|
@ -96,9 +120,9 @@ hash_delete (hash_table table, int nbuckexp, unsigned long key)
|
|||
if (prev)
|
||||
prev->next = bucket->next;
|
||||
else
|
||||
table[bucket_index] = bucket->next;
|
||||
h->table[bucket_index] = bucket->next;
|
||||
|
||||
XFREE (XMEM_HASH, bucket);
|
||||
XFREE (bucket);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,13 @@
|
|||
#ifndef __HASH_H
|
||||
#define __HASH_H
|
||||
|
||||
struct hash_table;
|
||||
|
||||
/* Hash table type and declaration macro. */
|
||||
typedef struct hash_item **hash_table;
|
||||
#define HASH_DECLARE(name,nbuckexp) struct hash_item *name[1 << nbuckexp]
|
||||
|
||||
|
||||
/* 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);
|
||||
struct hash_table *hash_new (int);
|
||||
void hash_free (struct hash_table *);
|
||||
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);
|
||||
|
||||
#endif /* __HASH_H */
|
||||
|
||||
|
|
1010
src/pobj/pobj.c
1010
src/pobj/pobj.c
File diff suppressed because it is too large
Load diff
172
src/pobj/xmem.c
172
src/pobj/xmem.c
|
@ -1,117 +1,79 @@
|
|||
#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
|
||||
/* Extended memory block info. */
|
||||
int mtype;
|
||||
struct xmem {
|
||||
char *file;
|
||||
int line;
|
||||
int size;
|
||||
struct xmem *prev;
|
||||
struct xmem *next;
|
||||
#endif /* HAVE_XMEM_DETAIL */
|
||||
|
||||
/* Dummy field used to infer alignment. */
|
||||
int dummy;
|
||||
int dummy; /* dummy field to infer alignment. */
|
||||
};
|
||||
#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;
|
||||
# define XMEM_OFFSET member_offset (struct xmem, dummy)
|
||||
#endif /* HAVE_XMEM_DETAIL */
|
||||
} xmem_stats[XMEM_MAX] = { { 0 } };
|
||||
#endif /* HAVE_XMEM */
|
||||
|
||||
|
||||
/* Default memory calls. */
|
||||
void *(*g_memfunc_malloc) (size_t) = malloc;
|
||||
void *(*g_memfunc_realloc) (void *, size_t) = realloc;
|
||||
void (*g_memfunc_free) (void *) = free;
|
||||
|
||||
|
||||
#ifdef HAVE_XMEM_DETAIL
|
||||
void *
|
||||
xmem_malloc (int mtype, char *file, int line, size_t size)
|
||||
xmem_malloc (char *file, int line, size_t size)
|
||||
{
|
||||
struct xmem *x;
|
||||
|
||||
x = (struct xmem *) g_memfunc_malloc (size + XMEM_OFFSET);
|
||||
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->line = line;
|
||||
x->size = size;
|
||||
|
||||
/* Attach to object type list. */
|
||||
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);
|
||||
return (void *) ((char *) x + XMEM_OFFSET);
|
||||
}
|
||||
|
||||
void
|
||||
xmem_free (int mtype, void *p)
|
||||
xmem_free (void *p)
|
||||
{
|
||||
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 */
|
||||
struct xmem *x = (struct xmem *) ((char *) p - XMEM_OFFSET);
|
||||
|
||||
g_memfunc_free (x);
|
||||
}
|
||||
#endif /* HAVE_XMEM_DETAIL */
|
||||
|
||||
|
||||
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)
|
||||
g_memfunc_malloc = memfunc_malloc;
|
||||
if (memfunc_realloc)
|
||||
g_memfunc_realloc = memfunc_realloc;
|
||||
if (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 *
|
||||
xmem_obj_file (void *p)
|
||||
xmem_get_file (void *p)
|
||||
{
|
||||
#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;
|
||||
#else
|
||||
return NULL;
|
||||
|
@ -142,10 +93,10 @@ xmem_obj_file (void *p)
|
|||
}
|
||||
|
||||
int
|
||||
xmem_obj_line (void *p)
|
||||
xmem_get_line (void *p)
|
||||
{
|
||||
#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;
|
||||
#else
|
||||
return 0;
|
||||
|
@ -153,49 +104,12 @@ xmem_obj_line (void *p)
|
|||
}
|
||||
|
||||
size_t
|
||||
xmem_obj_size (void *p)
|
||||
xmem_get_size (void *p)
|
||||
{
|
||||
#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;
|
||||
#else
|
||||
return 0;
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
#ifndef __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
|
||||
#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 */
|
||||
|
||||
void *xmem_malloc (int, char *, int, size_t);
|
||||
void xmem_free (int, void *);
|
||||
int xmem_memfunc (void *(*) (size_t), void (*) (void *));
|
||||
int xmem_obj_mtype (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 *));
|
||||
int xmem_memfunc (void *(*) (size_t), void *(*) (void *, size_t), void (*) (void *));
|
||||
char *xmem_get_file (void *);
|
||||
int xmem_get_line (void *);
|
||||
size_t xmem_get_size (void *);
|
||||
|
||||
#endif /* __XMEM_H */
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ main (int argc, char **argv)
|
|||
printf ("first-time init\n");
|
||||
/* Build list. */
|
||||
next = NULL;
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < 15000; i++) {
|
||||
pobj_start ();
|
||||
tmp = (struct item *) pobj_malloc (sizeof (struct item));
|
||||
if (! tmp) {
|
||||
|
|
Loading…
Reference in a new issue