Example #1
0
        public static UnsafeHashSet *Allocate <T>(int capacity, bool fixedSize = false)
            where T : unmanaged, IEquatable <T>
        {
            var valStride   = sizeof(T);
            var entryStride = sizeof(UnsafeHashCollection.Entry);

            // round capacity up to next prime
            capacity = UnsafeHashCollection.GetNextPrime(capacity);

            var valAlignment = Memory.GetAlignment(valStride);

            // the alignment for entry/key/val, we can't have less than ENTRY_ALIGNMENT
            // bytes alignment because entries are 16 bytes with 1 x pointer + 2 x 4 byte integers
            var alignment = Math.Max(UnsafeHashCollection.Entry.ALIGNMENT, valAlignment);

            // calculate strides for all elements
            valStride   = Memory.RoundToAlignment(valStride, alignment);
            entryStride = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry), alignment);

            // dictionary ptr
            UnsafeHashSet *set;

            if (fixedSize)
            {
                var sizeOfHeader        = Memory.RoundToAlignment(sizeof(UnsafeHashSet), alignment);
                var sizeOfBucketsBuffer = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment);
                var sizeofEntriesBuffer = (entryStride + valStride) * capacity;

                // allocate memory
                var ptr = Memory.MallocAndZero(sizeOfHeader + sizeOfBucketsBuffer + sizeofEntriesBuffer, alignment);

                // start of memory is the dict itself
                set = (UnsafeHashSet *)ptr;

                // buckets are offset by header size
                set->_collection.Buckets = (UnsafeHashCollection.Entry * *)((byte *)ptr + sizeOfHeader);

                // initialize fixed buffer
                UnsafeBuffer.InitFixed(&set->_collection.Entries, (byte *)ptr + (sizeOfHeader + sizeOfBucketsBuffer), capacity, entryStride + valStride);
            }
            else
            {
                // allocate dict, buckets and entries buffer separately
                set = Memory.MallocAndZero <UnsafeHashSet>();
                set->_collection.Buckets = (UnsafeHashCollection.Entry * *)Memory.MallocAndZero(sizeof(UnsafeHashCollection.Entry * *) * capacity, sizeof(UnsafeHashCollection.Entry * *));

                // init dynamic buffer
                UnsafeBuffer.InitDynamic(&set->_collection.Entries, capacity, entryStride + valStride);
            }

            set->_collection.FreeCount = 0;
            set->_collection.UsedCount = 0;
            set->_collection.KeyOffset = entryStride;
            set->_typeHandle           = typeof(T).TypeHandle.Value;

            return(set);
        }
Example #2
0
        int                  _valueOffset;     // Readonly

        public static UnsafeDictionary *Allocate <K, V>(int capacity, bool fixedSize = false)
            where K : unmanaged, IEquatable <K>
            where V : unmanaged
        {
            var keyStride   = sizeof(K);
            var valStride   = sizeof(V);
            var entryStride = sizeof(UnsafeHashCollection.Entry);

            // round capacity up to next prime
            capacity = UnsafeHashCollection.GetNextPrime(capacity);

            var keyAlignment = Memory.GetAlignment(keyStride);
            var valAlignment = Memory.GetAlignment(valStride);

            // the alignment for entry/key/val, we can't have less than ENTRY_ALIGNMENT
            // bytes alignment because entries are 8 bytes with 2 x 32 bit integers
            var alignment = Math.Max(UnsafeHashCollection.Entry.ALIGNMENT, Math.Max(keyAlignment, valAlignment));

            // calculate strides for all elements
            keyStride   = Memory.RoundToAlignment(keyStride, alignment);
            valStride   = Memory.RoundToAlignment(valStride, alignment);
            entryStride = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry), alignment);

            // map ptr
            UnsafeDictionary *map;

            if (fixedSize)
            {
                var sizeOfHeader        = Memory.RoundToAlignment(sizeof(UnsafeDictionary), alignment);
                var sizeOfBucketsBuffer = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment);
                var sizeofEntriesBuffer = (entryStride + keyStride + valStride) * capacity;

                // allocate memory
                var ptr = Memory.MallocAndZero(sizeOfHeader + sizeOfBucketsBuffer + sizeofEntriesBuffer, alignment);

                // start of memory is the dict itself
                map = (UnsafeDictionary *)ptr;

                // buckets are offset by header size
                map->_collection.Buckets = (UnsafeHashCollection.Entry * *)((byte *)ptr + sizeOfHeader);

                // initialize fixed buffer
                UnsafeBuffer.InitFixed(&map->_collection.Entries, (byte *)ptr + (sizeOfHeader + sizeOfBucketsBuffer), capacity, entryStride + keyStride + valStride);
            }
            else
            {
                // allocate dict, buckets and entries buffer separately
                map = Memory.MallocAndZero <UnsafeDictionary>();
                map->_collection.Buckets = (UnsafeHashCollection.Entry * *)Memory.MallocAndZero(sizeof(UnsafeHashCollection.Entry * *) * capacity, sizeof(UnsafeHashCollection.Entry * *));

                // init dynamic buffer
                UnsafeBuffer.InitDynamic(&map->_collection.Entries, capacity, entryStride + keyStride + valStride);
            }

            // header init
            map->_collection.FreeCount = 0;
            map->_collection.UsedCount = 0;
            map->_collection.KeyOffset = entryStride;
            map->_typeHandleKey        = typeof(K).TypeHandle.Value;
            map->_typeHandleValue      = typeof(V).TypeHandle.Value;

            map->_valueOffset = entryStride + keyStride;

            return(map);
        }