/// -- 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);
        }
Exemple #2
0
        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;
        }