private void rehash(int newsize, bool forceNewHashCode)
{
// reset occupancy
_occupancy = 0;
// Don't replace any internal state until we've finished adding to the
// new bucket[]. This serves two purposes:
// 1) Allow concurrent readers to see valid hashtable contents
// at all times
// 2) Protect against an OutOfMemoryException while allocating this
// new bucket[].
bucket[] newBuckets = new bucket[newsize];
// rehash table into new buckets
int nb;
for (nb = 0; nb < _buckets.Length; nb++)
{
bucket oldb = _buckets[nb];
if ((oldb.key != null) && (oldb.key != _buckets))
{
int hashcode = ((forceNewHashCode ? GetHash(oldb.key) : oldb.hash_coll) & 0x7FFFFFFF);
putEntry(newBuckets, oldb.key, oldb.val, hashcode);
}
}
// New bucket[] is good to go - replace buckets and other internal state.
_isWriterInProgress = true;
_buckets = newBuckets;
_loadsize = (int)(_loadFactor * newsize);
UpdateVersion();
_isWriterInProgress = false;
// minimum size of hashtable is 3 now and maximum loadFactor is 0.72 now.
Debug.Assert(_loadsize < newsize, "Our current implementation means this is not possible.");
return;
}