Beispiel #1
0
        public static void AllocateHashMap <TKey, TValue>(int length, int bucketLength, Allocator label,
                                                          out NativeHashMapData *outBuf)
            where TKey : struct
            where TValue : struct
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <TKey>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeHashMap<{0},{1}> must be blittable",
                                                          typeof(TKey), typeof(TValue)));
            }
            if (!UnsafeUtility.IsBlittable <TValue>())
            {
                throw new ArgumentException(string.Format("{1} used in NativeHashMap<{0},{1}> must be blittable",
                                                          typeof(TKey), typeof(TValue)));
            }
#endif

            NativeHashMapData *data = (NativeHashMapData *)UnsafeUtility.Malloc(sizeof(NativeHashMapData),
                                                                                UnsafeUtility.AlignOf <NativeHashMapData>(), label);

            bucketLength = CollectionHelper.CeilPow2(bucketLength);

            data->capacity           = length;
            data->bucketCapacityMask = bucketLength - 1;

            int keyOffset, nextOffset, bucketOffset;
            int totalSize = CalculateDataSize <TKey, TValue>(length, bucketLength, out keyOffset, out nextOffset,
                                                             out bucketOffset);

            data->values  = (byte *)UnsafeUtility.Malloc(totalSize, JobsUtility.CacheLineSize, label);
            data->keys    = data->values + keyOffset;
            data->next    = data->values + nextOffset;
            data->buckets = data->values + bucketOffset;

            outBuf = data;
        }
Beispiel #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;
        }