/// -- Internals unsafe static void IntroSort <T, U>(void *array, int length, U comp) where T : struct where U : IComparer <T> { IntroSort <T, U>(array, 0, length - 1, 2 * CollectionHelper.Log2Floor(length), comp); }
public static void ReallocateHashMap <TKey, TValue>(NativeHashMapData *data, int newCapacity, int newBucketCapacity, Allocator label) where TKey : struct where TValue : struct { newBucketCapacity = CollectionHelper.CeilPow2(newBucketCapacity); if (data->capacity == newCapacity && (data->bucketCapacityMask + 1) == newBucketCapacity) { return; } if (data->capacity > newCapacity) { throw new Exception("Shrinking a hash map is not supported"); } int keyOffset, nextOffset, bucketOffset; int totalSize = CalculateDataSize <TKey, TValue>(newCapacity, newBucketCapacity, out keyOffset, out nextOffset, out bucketOffset); byte *newData = (byte *)UnsafeUtility.Malloc(totalSize, JobsUtility.CacheLineSize, label); byte *newKeys = newData + keyOffset; byte *newNext = newData + nextOffset; byte *newBuckets = newData + bucketOffset; // The items are taken from a free-list and might not be tightly packed, copy all of the old capcity UnsafeUtility.MemCpy(newData, data->values, data->capacity * UnsafeUtility.SizeOf <TValue>()); UnsafeUtility.MemCpy(newKeys, data->keys, data->capacity * UnsafeUtility.SizeOf <TKey>()); UnsafeUtility.MemCpy(newNext, data->next, data->capacity * UnsafeUtility.SizeOf <int>()); for (int emptyNext = data->capacity; emptyNext < newCapacity; ++emptyNext) { ((int *)newNext)[emptyNext] = -1; } // re-hash the buckets, first clear the new bucket list, then insert all values from the old list for (int bucket = 0; bucket < newBucketCapacity; ++bucket) { ((int *)newBuckets)[bucket] = -1; } for (int bucket = 0; bucket <= data->bucketCapacityMask; ++bucket) { int *buckets = (int *)data->buckets; int *nextPtrs = (int *)newNext; while (buckets[bucket] >= 0) { int curEntry = buckets[bucket]; buckets[bucket] = nextPtrs[curEntry]; int newBucket = UnsafeUtility.ReadArrayElement <TKey>(data->keys, curEntry).GetHashCode() & (newBucketCapacity - 1); nextPtrs[curEntry] = ((int *)newBuckets)[newBucket]; ((int *)newBuckets)[newBucket] = curEntry; } } UnsafeUtility.Free(data->values, label); if (data->allocatedIndexLength > data->capacity) { data->allocatedIndexLength = data->capacity; } data->values = newData; data->keys = newKeys; data->next = newNext; data->buckets = newBuckets; data->capacity = newCapacity; data->bucketCapacityMask = newBucketCapacity - 1; }