X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FHash.c;h=9c9b2bce423974e13e5acb3afe0caa6a2b132002;hb=7d9eb2e45b4a9ff4cb053b1ec37602be88528b62;hp=1d80640c4ab171ed7a750d120cb2c29601c01048;hpb=9f2ceb4da7dfbc1cfd09ce54610ebe64288b9007;p=ghc-hetmet.git diff --git a/rts/Hash.c b/rts/Hash.c index 1d80640..9c9b2bc 100644 --- a/rts/Hash.c +++ b/rts/Hash.c @@ -10,10 +10,10 @@ #include "PosixSource.h" #include "Rts.h" + #include "Hash.h" #include "RtsUtils.h" -#include #include #define HSEGSIZE 1024 /* Size of a single hash table segment */ @@ -27,16 +27,16 @@ /* Linked list of (key, data) pairs for separate chaining */ -struct hashlist { +typedef struct hashlist { StgWord key; void *data; struct hashlist *next; /* Next cell in bucket chain (same hash value) */ -}; - -typedef struct hashlist HashList; +} HashList; -typedef int HashFunction(HashTable *table, StgWord key); -typedef int CompareFunction(StgWord key1, StgWord key2); +typedef struct chunklist { + HashList *chunk; + struct chunklist *next; +} HashListChunk; struct hashtable { int split; /* Next bucket to split when expanding */ @@ -46,7 +46,9 @@ struct hashtable { int kcount; /* Number of keys */ int bcount; /* Number of buckets */ HashList **dir[HDIRSIZE]; /* Directory of segments */ - HashFunction *hash; /* hash function */ + HashList *freeList; /* free list of HashLists */ + HashListChunk *chunks; + HashFunction *hash; /* hash function */ CompareFunction *compare; /* key comparison function */ }; @@ -55,7 +57,7 @@ struct hashtable { * next bucket to be split, re-hash using the larger table. * -------------------------------------------------------------------------- */ -static int +int hashWord(HashTable *table, StgWord key) { int bucket; @@ -73,7 +75,7 @@ hashWord(HashTable *table, StgWord key) return bucket; } -static int +int hashStr(HashTable *table, char *key) { int h, bucket; @@ -210,30 +212,23 @@ lookupHashTable(HashTable *table, StgWord key) * no effort to actually return the space to the malloc arena. * -------------------------------------------------------------------------- */ -static HashList *freeList = NULL; - -static struct chunkList { - void *chunk; - struct chunkList *next; -} *chunks; - static HashList * -allocHashList(void) +allocHashList (HashTable *table) { HashList *hl, *p; - struct chunkList *cl; + HashListChunk *cl; - if ((hl = freeList) != NULL) { - freeList = hl->next; + if ((hl = table->freeList) != NULL) { + table->freeList = hl->next; } else { hl = stgMallocBytes(HCHUNK * sizeof(HashList), "allocHashList"); cl = stgMallocBytes(sizeof (*cl), "allocHashList: chunkList"); - cl->chunk = hl; - cl->next = chunks; - chunks = cl; + cl->chunk = hl; + cl->next = table->chunks; + table->chunks = cl; - freeList = hl + 1; - for (p = freeList; p < hl + HCHUNK - 1; p++) + table->freeList = hl + 1; + for (p = table->freeList; p < hl + HCHUNK - 1; p++) p->next = p + 1; p->next = NULL; } @@ -241,10 +236,10 @@ allocHashList(void) } static void -freeHashList(HashList *hl) +freeHashList (HashTable *table, HashList *hl) { - hl->next = freeList; - freeList = hl; + hl->next = table->freeList; + table->freeList = hl; } void @@ -267,7 +262,7 @@ insertHashTable(HashTable *table, StgWord key, void *data) segment = bucket / HSEGSIZE; index = bucket % HSEGSIZE; - hl = allocHashList(); + hl = allocHashList(table); hl->key = key; hl->data = data; @@ -295,7 +290,7 @@ removeHashTable(HashTable *table, StgWord key, void *data) table->dir[segment][index] = hl->next; else prev->next = hl->next; - freeHashList(hl); + freeHashList(table,hl); table->kcount--; return hl->data; } @@ -320,6 +315,7 @@ freeHashTable(HashTable *table, void (*freeDataFun)(void *) ) long index; HashList *hl; HashList *next; + HashListChunk *cl, *cl_next; /* The last bucket with something in it is table->max + table->split - 1 */ segment = (table->max + table->split - 1) / HSEGSIZE; @@ -331,14 +327,18 @@ freeHashTable(HashTable *table, void (*freeDataFun)(void *) ) next = hl->next; if (freeDataFun != NULL) (*freeDataFun)(hl->data); - freeHashList(hl); - } + } index--; } stgFree(table->dir[segment]); segment--; index = HSEGSIZE - 1; } + for (cl = table->chunks; cl != NULL; cl = cl_next) { + cl_next = cl->next; + stgFree(cl->chunk); + stgFree(cl); + } stgFree(table); } @@ -347,7 +347,7 @@ freeHashTable(HashTable *table, void (*freeDataFun)(void *) ) * initializing all of the first segment's hash buckets to NULL. * -------------------------------------------------------------------------- */ -static HashTable * +HashTable * allocHashTable_(HashFunction *hash, CompareFunction *compare) { HashTable *table; @@ -366,6 +366,8 @@ allocHashTable_(HashFunction *hash, CompareFunction *compare) table->mask2 = 2 * HSEGSIZE - 1; table->kcount = 0; table->bcount = HSEGSIZE; + table->freeList = NULL; + table->chunks = NULL; table->hash = hash; table->compare = compare; @@ -388,11 +390,5 @@ allocStrHashTable(void) void exitHashTable(void) { - struct chunkList *cl; - - while ((cl = chunks) != NULL) { - chunks = cl->next; - stgFree(cl->chunk); - stgFree(cl); - } + /* nothing to do */ }