Commit ed0222d6 authored by simonmar's avatar simonmar

[project @ 2002-04-09 12:55:11 by simonmar]

- Revert rev. 1.7, i.e. go back to using malloc/free and a free list
  to manage hash list cells, because the arena method doesn't recycle
  used cells, resulting in memory leaks.

- Add a freeHashList() call which was missing in removeHashTable().
parent 74c05fae
/*-----------------------------------------------------------------------------
* $Id: Hash.c,v 1.7 2001/11/26 13:06:49 simonmar Exp $
* $Id: Hash.c,v 1.8 2002/04/09 12:55:11 simonmar Exp $
*
* (c) The AQUA Project, Glasgow University, 1995-1998
* (c) The GHC Team, 1999
......@@ -13,7 +13,6 @@
#include "Rts.h"
#include "Hash.h"
#include "RtsUtils.h"
#include "Arena.h"
#define HSEGSIZE 1024 /* Size of a single hash table segment */
/* Also the minimum size of a hash table */
......@@ -47,7 +46,6 @@ struct hashtable {
HashList **dir[HDIRSIZE]; /* Directory of segments */
HashFunction *hash; /* hash function */
CompareFunction *compare; /* key comparison function */
Arena *arena;
};
/* -----------------------------------------------------------------------------
......@@ -121,6 +119,7 @@ allocSegment(HashTable *table, int segment)
"allocSegment");
}
/* -----------------------------------------------------------------------------
* Expand the larger hash table by one bucket, and split one bucket
* from the smaller table into two parts. Only the bucket referenced
......@@ -203,6 +202,39 @@ lookupHashTable(HashTable *table, StgWord key)
return NULL;
}
/* -----------------------------------------------------------------------------
* We allocate the hashlist cells in large chunks to cut down on malloc
* overhead. Although we keep a free list of hashlist cells, we make
* no effort to actually return the space to the malloc arena.
* -------------------------------------------------------------------------- */
static HashList *freeList = NULL;
static HashList *
allocHashList(void)
{
HashList *hl, *p;
if ((hl = freeList) != NULL) {
freeList = hl->next;
} else {
hl = stgMallocBytes(HCHUNK * sizeof(HashList), "allocHashList");
freeList = hl + 1;
for (p = freeList; p < hl + HCHUNK - 1; p++)
p->next = p + 1;
p->next = NULL;
}
return hl;
}
static void
freeHashList(HashList *hl)
{
hl->next = freeList;
freeList = hl;
}
void
insertHashTable(HashTable *table, StgWord key, void *data)
{
......@@ -222,7 +254,7 @@ insertHashTable(HashTable *table, StgWord key, void *data)
segment = bucket / HSEGSIZE;
index = bucket % HSEGSIZE;
hl = arenaAlloc(table->arena, sizeof(struct hashlist));
hl = allocHashList();
hl->key = key;
hl->data = data;
......@@ -250,6 +282,7 @@ removeHashTable(HashTable *table, StgWord key, void *data)
table->dir[segment][index] = hl->next;
else
prev->next = hl->next;
freeHashList(hl);
table->kcount--;
return hl->data;
}
......@@ -268,7 +301,7 @@ removeHashTable(HashTable *table, StgWord key, void *data)
* -------------------------------------------------------------------------- */
void
freeHashTable( HashTable *table, void (*freeDataFun)(void *) )
freeHashTable(HashTable *table, void (*freeDataFun)(void *) )
{
long segment;
long index;
......@@ -278,23 +311,21 @@ freeHashTable( HashTable *table, void (*freeDataFun)(void *) )
/* The last bucket with something in it is table->max + table->split - 1 */
segment = (table->max + table->split - 1) / HSEGSIZE;
index = (table->max + table->split - 1) % HSEGSIZE;
while (segment >= 0) {
if (freeDataFun != NULL) {
while (index >= 0) {
for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
next = hl->next;
while (index >= 0) {
for (hl = table->dir[segment][index]; hl != NULL; hl = next) {
next = hl->next;
if (freeDataFun != NULL)
(*freeDataFun)(hl->data);
}
index--;
freeHashList(hl);
}
index--;
}
free(table->dir[segment]);
segment--;
index = HSEGSIZE - 1;
}
arenaFree(table->arena);
free(table);
}
......@@ -311,8 +342,6 @@ allocHashTable_(HashFunction *hash, CompareFunction *compare)
table = stgMallocBytes(sizeof(HashTable),"allocHashTable");
table->arena = newArena();
allocSegment(table, 0);
for (hb = table->dir[0]; hb < table->dir[0] + HSEGSIZE; hb++)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment