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); }
static void Expand(UnsafeHashCollection *collection) { UDebug.Assert(collection->Entries.Dynamic == 1); // We need to grab the pext prime, so at least current length + 1 var capacity = GetNextPrime(collection->Entries.Length + 1); UDebug.Assert(capacity >= collection->Entries.Length); var newBuckets = (Entry **)Memory.MallocAndZero(capacity * sizeof(Entry * *), sizeof(Entry * *)); var newEntries = default(UnsafeBuffer); UnsafeBuffer.InitDynamic(&newEntries, capacity, collection->Entries.Stride); UnsafeBuffer.Copy(collection->Entries, 0, newEntries, 0, collection->Entries.Length); collection->FreeHead = null; collection->FreeCount = 0; for (int i = collection->Entries.Length - 1; i >= 0; --i) { var entry = (Entry *)((byte *)newEntries.Ptr + (i * newEntries.Stride)); if (entry->State == EntryState.Used) { var bucketHash = entry->Hash % capacity; // assign current entry in buckets as next entry->Next = newBuckets[bucketHash]; // assign entry as new bucket head newBuckets[bucketHash] = entry; } // entry is in free list else if (entry->State == EntryState.Free) { // assign free list as next entry->Next = collection->FreeHead; // re-assign free list to entry collection->FreeHead = entry; collection->FreeCount = collection->FreeCount + 1; } } // free old memory Memory.Free(collection->Buckets); UnsafeBuffer.Free(&collection->Entries); // new storage collection->Buckets = newBuckets; collection->Entries = newEntries; }
int _valueOffset; // Readonly public static UnsafeSortedDictionary *Allocate <K, V>(int capacity, bool fixedSize = false) where K : unmanaged, IComparable <K> where V : unmanaged { var keyStride = sizeof(K); var valStride = sizeof(V); var entryStride = sizeof(UnsafeHashCollection.Entry); var keyAlignment = Memory.GetAlignment(keyStride); var valAlignment = Memory.GetAlignment(valStride); var alignment = Math.Max(UnsafeHashCollection.Entry.ALIGNMENT, Math.Max(keyAlignment, valAlignment)); keyStride = Memory.RoundToAlignment(keyStride, alignment); valStride = Memory.RoundToAlignment(valStride, alignment); entryStride = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry), alignment); var totalStride = keyStride + valStride + entryStride; UnsafeSortedDictionary *map; if (fixedSize) { var sizeOfHeader = Memory.RoundToAlignment(sizeof(UnsafeDictionary), alignment); var sizeOfBucketsBuffer = Memory.RoundToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment); var sizeofEntriesBuffer = totalStride * capacity; // allocate memory var ptr = Memory.MallocAndZero(sizeOfHeader + sizeOfBucketsBuffer + sizeofEntriesBuffer, alignment); map = (UnsafeSortedDictionary *)ptr; UnsafeBuffer.InitFixed(&map->_collection.Entries, (byte *)ptr + (sizeOfHeader + sizeOfBucketsBuffer), capacity, totalStride); } else { map = Memory.MallocAndZero <UnsafeSortedDictionary>(); UnsafeBuffer.InitDynamic(&map->_collection.Entries, capacity, totalStride); } // 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); }
public static UnsafeSortedSet *Allocate <T>(int capacity, bool fixedSize = false) where T : unmanaged, IComparable <T> { var valStride = sizeof(T); var entryStride = sizeof(UnsafeOrderedCollection.Entry); var valAlignment = Memory.GetAlignment(valStride); // the alignment for entry/key/val, we can't have less than ENTRY_ALIGNMENT // bytes alignment because entries are 12 bytes with 3 x 32 bit integers var alignment = Math.Max(UnsafeOrderedCollection.Entry.ALIGNMENT, valAlignment); // calculate strides for all elements valStride = Memory.RoundToAlignment(valStride, alignment); entryStride = Memory.RoundToAlignment(entryStride, alignment); // dictionary ptr UnsafeSortedSet *set; if (fixedSize) { var sizeOfHeader = Memory.RoundToAlignment(sizeof(UnsafeSortedSet), alignment); var sizeofEntriesBuffer = (entryStride + valStride) * capacity; // allocate memory var ptr = Memory.MallocAndZero(sizeOfHeader + sizeofEntriesBuffer, alignment); // start of memory is the set itself set = (UnsafeSortedSet *)ptr; // initialize fixed buffer UnsafeBuffer.InitFixed(&set->_collection.Entries, (byte *)ptr + sizeOfHeader, capacity, entryStride + valStride); } else { // allocate set separately set = Memory.MallocAndZero <UnsafeSortedSet>(); // 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); }
public static UnsafeStack *Allocate <T>(int capacity, bool fixedSize = false) where T : unmanaged { if (capacity < 1) { throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity))); } var stride = sizeof(T); UnsafeStack *stack; // fixedSize stack means we are allocating the memory // for the stack header and the items in it as one block if (fixedSize) { var alignment = Memory.GetAlignment(stride); // align stack header size to the elements alignment var sizeOfStack = Memory.RoundToAlignment(sizeof(UnsafeStack), alignment); var sizeOfArray = stride * capacity; // allocate memory for stack and array with the correct alignment var ptr = Memory.MallocAndZero(sizeOfStack + sizeOfArray, alignment); // grab stack ptr stack = (UnsafeStack *)ptr; // initialize fixed buffer from same block of memory as the stack UnsafeBuffer.InitFixed(&stack->_items, (byte *)ptr + sizeOfStack, capacity, stride); } // dynamic sized stack means we're allocating the stack header // and its memory separately else { // allocate stack separately stack = Memory.MallocAndZero <UnsafeStack>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&stack->_items, capacity, stride); } // just safety, make sure count is 0 stack->_count = 0; stack->_typeHandle = typeof(T).TypeHandle.Value; return(stack); }
public static void SetCapacity(UnsafeList *list, int capacity) { UDebug.Assert(list != null); UDebug.Assert(list->_items.Ptr != null); UDebug.Assert(capacity > 0); if (list->_items.Dynamic == 0) { throw new InvalidOperationException(ThrowHelper.InvalidOperation_CollectionFull); } // no change in capacity if (capacity == list->_items.Length) { return; } // allocate new items UnsafeBuffer newItems = default; UnsafeBuffer.InitDynamic(&newItems, capacity, list->_items.Stride); // if have anything in list, copy it if (list->_count > 0) { // also make sure that count is // not larger than the new capacity if (list->_count > capacity) { list->_count = capacity; } // copy over elements UnsafeBuffer.Copy(list->_items, 0, newItems, 0, list->_count); } // if an existing buffer was here, free it if (list->_items.Ptr != null) { UnsafeBuffer.Free(&list->_items); } // assign new buffer list->_items = newItems; }
static void Expand(UnsafeOrderedCollection *collection) { UDebug.Assert(collection->Entries.Dynamic == 1); UDebug.Assert(collection->FreeCount == 0); UDebug.Assert(collection->FreeHead == 0); var capacity = collection->Entries.Length * 2; var newEntries = default(UnsafeBuffer); UnsafeBuffer.InitDynamic(&newEntries, capacity, collection->Entries.Stride); UnsafeBuffer.Copy(collection->Entries, 0, newEntries, 0, collection->Entries.Length); // free old memory UnsafeBuffer.Free(&collection->Entries); // new storage collection->Entries = newEntries; }
public static UnsafeQueue *Allocate <T>(int capacity, bool fixedSize = false) where T : unmanaged { if (capacity < 1) { throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity))); } int stride = sizeof(T); UnsafeQueue *queue; // fixedSize queue means we are allocating the memory for the header and the items in it as one block if (fixedSize) { var alignment = Memory.GetAlignment(stride); var sizeOfQueue = Memory.RoundToAlignment(sizeof(UnsafeQueue), alignment); var sizeOfArray = stride * capacity; var ptr = Memory.MallocAndZero(sizeOfQueue + sizeOfArray, alignment); // cast ptr to queue queue = (UnsafeQueue *)ptr; // initialize fixed buffer from same block of memory as the stack UnsafeBuffer.InitFixed(&queue->_items, (byte *)ptr + sizeOfQueue, capacity, stride); } // dynamic sized queue means we're allocating the stack header and its memory separately else { // allocate memory for queue queue = Memory.MallocAndZero <UnsafeQueue>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&queue->_items, capacity, stride); } queue->_head = 0; queue->_tail = 0; queue->_count = 0; queue->_typeHandle = typeof(T).TypeHandle.Value; return(queue); }
private static void Expand(UnsafeStack *stack) { // new buffer for elements UnsafeBuffer newItems = default; // initialize to double size of existing one int newSize = stack->_items.Length == 0 ? DEFAULT_CAPACITY : stack->_items.Length * 2; UnsafeBuffer.InitDynamic(&newItems, newSize, stack->_items.Stride); // copy memory over from previous items UnsafeBuffer.Copy(stack->_items, 0, newItems, 0, stack->_items.Length); // free old buffer UnsafeBuffer.Free(&stack->_items); // replace buffer with new stack->_items = newItems; }
public static UnsafeList *Allocate <T>(int capacity, bool fixedSize = false) where T : unmanaged { if (capacity < 1) { throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity))); } int stride = sizeof(T); UnsafeList *list; // fixedSize means we are allocating the memory for the collection header and the items in it as one block if (fixedSize) { var alignment = Memory.GetAlignment(stride); // align header size to the elements alignment var sizeOfHeader = Memory.RoundToAlignment(sizeof(UnsafeList), alignment); var sizeOfBuffer = stride * capacity; // allocate memory for list and array with the correct alignment var ptr = Memory.MallocAndZero(sizeOfHeader + sizeOfBuffer); // grab header ptr list = (UnsafeList *)ptr; // initialize fixed buffer from same block of memory as the collection, offset by sizeOfHeader UnsafeBuffer.InitFixed(&list->_items, (byte *)ptr + sizeOfHeader, capacity, stride); } else { // allocate collection separately list = Memory.MallocAndZero <UnsafeList>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&list->_items, capacity, stride); } list->_count = 0; list->_typeHandle = typeof(T).TypeHandle.Value; return(list); }
static void Expand(UnsafeQueue *queue, int capacity) { UDebug.Assert(capacity > 0); // queue has to be dynamic and capacity we're going to have to be larger UDebug.Assert(queue->_items.Dynamic == 1); UDebug.Assert(queue->_items.Length < capacity); // new buffer for elements UnsafeBuffer newItems = default; // initialize to double size of existing one UnsafeBuffer.InitDynamic(&newItems, capacity, queue->_items.Stride); if (queue->_count > 0) { // when head is 'ahead' or at tail it means that we're wrapping around if (queue->_head >= queue->_tail) { // so we need to copy head first, from (head, length-head) into (0, length-head) UnsafeBuffer.Copy(queue->_items, queue->_head, newItems, 0, queue->_items.Length - queue->_head); // and then copy tail, from (0, tail) into (length-head, tail) UnsafeBuffer.Copy(queue->_items, 0, newItems, queue->_items.Length - queue->_head, queue->_tail); } else { // if not, we can just copy from (tail, count) into (0, count) UnsafeBuffer.Copy(queue->_items, queue->_head, newItems, 0, queue->_count); } } // free existing buffer UnsafeBuffer.Free(&queue->_items); queue->_items = newItems; queue->_head = 0; queue->_tail = queue->_count % queue->_items.Length; }
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); }