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)())