506484c03bae4b9a7d61c5a56b928e773a0c83a7 angie Tue Apr 16 14:02:22 2019 -0700 Added hashNewLm/newHashLm so an external lm can be passed in and used for all hash allocations. diff --git src/lib/hash.c src/lib/hash.c index 82a7924..2308617 100644 --- src/lib/hash.c +++ src/lib/hash.c @@ -342,52 +342,73 @@ { int num = ptToInt(hel->val); sum += (long long)num; } } return sum; } void hashIntReset(struct hash *hash) /* Reset all values in hash of ints to 0. Reset element count to 0. */ { memset(hash->table, 0, hash->size * sizeof hash->table[0]); hash->elCount = 0; } +struct hash *newHashLm(int powerOfTwoSize, struct lm *lm) +/* Returns new hash table using the given lm. Recommended lm block size is 256B to 64kB, + * depending on powerOfTwoSize. */ +{ +struct hash *hash = lm ? lmAlloc(lm, sizeof(*hash)) : needMem(sizeof(*hash)); +if (powerOfTwoSize == 0) + powerOfTwoSize = 12; +assert(powerOfTwoSize <= hashMaxSize && powerOfTwoSize > 0); +hash->powerOfTwoSize = powerOfTwoSize; +hash->size = (1<<powerOfTwoSize); +hash->lm = lm; +hash->mask = hash->size-1; +if (lm) + lmAllocArray(hash->lm, hash->table, hash->size); +else + AllocArray(hash->table, hash->size); +hash->autoExpand = TRUE; +hash->expansionFactor = defaultExpansionFactor; /* Expand when elCount > size*expansionFactor */ +return hash; +} + struct hash *newHashExt(int powerOfTwoSize, boolean useLocalMem) /* Returns new hash table. Uses local memory optionally. */ { -struct hash *hash = needMem(sizeof(*hash)); +struct hash *hash = NULL; +if (useLocalMem) + { int memBlockPower = 16; if (powerOfTwoSize == 0) powerOfTwoSize = 12; assert(powerOfTwoSize <= hashMaxSize && powerOfTwoSize > 0); -hash->powerOfTwoSize = powerOfTwoSize; -hash->size = (1<<powerOfTwoSize); /* Make size of memory block for allocator vary between * 256 bytes and 64k depending on size of table. */ if (powerOfTwoSize < 8) memBlockPower = 8; else if (powerOfTwoSize < 16) memBlockPower = powerOfTwoSize; -if (useLocalMem) - hash->lm = lmInit(1<<memBlockPower); -hash->mask = hash->size-1; -AllocArray(hash->table, hash->size); -hash->autoExpand = TRUE; -hash->expansionFactor = defaultExpansionFactor; /* Expand when elCount > size*expansionFactor */ + struct lm *ownLm = lmInit(1<<memBlockPower); + hash = newHashLm(powerOfTwoSize, ownLm); + hash->ownLm = TRUE; + } +else + hash = newHashLm(powerOfTwoSize, NULL); return hash; } void hashReverseAllBucketLists(struct hash *hash) /* Reverse all hash bucket list. You might do this to * get them back in the same order things were added to the hash */ { int i; for (i=0; i<hash->size; ++i) { struct hashEl *hel = hash->table[i]; if (hel != NULL && hel->next != NULL) slReverse(&hash->table[i]); } } @@ -398,47 +419,51 @@ int oldHashSize = hash->size; struct hashEl **oldTable = hash->table; if (powerOfTwoSize == 0) powerOfTwoSize = 12; if (powerOfTwoSize > hashMaxSize) powerOfTwoSize = hashMaxSize; if (hash->powerOfTwoSize == powerOfTwoSize) return; assert(powerOfTwoSize <= hashMaxSize && powerOfTwoSize > 0); hash->powerOfTwoSize = powerOfTwoSize; hash->size = (1<<powerOfTwoSize); hash->mask = hash->size-1; +if (hash->lm) + lmAllocArray(hash->lm, hash->table, hash->size); +else AllocArray(hash->table, hash->size); int i; struct hashEl *hel, *next; for (i=0; i<oldHashSize; ++i) { for (hel = oldTable[i]; hel != NULL; hel = next) { next = hel->next; int hashVal = hel->hashVal & hash->mask; hel->next = hash->table[hashVal]; hash->table[hashVal] = hel; } } /* restore original list order */ hashReverseAllBucketLists(hash); +if (!hash->lm) freeMem(oldTable); hash->numResizes++; } struct hash *hashFromSlNameList(void *list) /* Create a hash out of a list of slNames. */ { struct hash *hash = NULL; struct slName *namedList = list, *item; if (!list) return NULL; hash = newHash(0); for (item = namedList; item != NULL; item = item->next) hashAdd(hash, item->name, item); @@ -611,47 +636,51 @@ { struct hashEl *hel = hashNext(cookie); if (hel == NULL) return NULL; else return hel->name; } void freeHash(struct hash **pHash) /* Free up hash table. */ { struct hash *hash = *pHash; if (hash == NULL) return; if (hash->lm) + { + if (hash->ownLm) lmCleanup(&hash->lm); + *pHash = NULL; + } else { int i; struct hashEl *hel, *next; for (i=0; i<hash->size; ++i) { for (hel = hash->table[i]; hel != NULL; hel = next) { next = hel->next; freeHashEl(hel); } } - } freeMem(hash->table); freez(pHash); } +} void freeHashAndVals(struct hash **pHash) /* Free up hash table and all values associated with it. * (Just calls freeMem on each hel->val) */ { struct hash *hash; if ((hash = *pHash) != NULL) { hashTraverseVals(hash, freeMem); freeHash(pHash); } } void hashFreeWithVals(struct hash **pHash, void (freeFunc)())