public static UnsafeArray *Allocate <T>(int size) where T : unmanaged { if (size < 1) { throw new InvalidOperationException(ARRAY_SIZE_LESS_THAN_ONE); } var alignment = AllocHelper.GetAlignmentForArrayElement(sizeof(T)); // pad the alignment of the array header var arrayStructSize = AllocHelper.RoundUpToAlignment(sizeof(UnsafeArray), alignment); var arrayMemorySize = size * sizeof(T); // allocate memory for header + elements, aligned to 'alignment' var ptr = AllocHelper.MallocAndClear(arrayStructSize + arrayMemorySize, alignment); UnsafeArray *array; array = (UnsafeArray *)ptr; array->_buffer = ((byte *)ptr) + arrayStructSize; array->_length = size; array->_typeHandle = typeof(T).TypeHandle.Value; return(array); }
public static UnsafeRingBuffer *Allocate(int capacity, int stride, bool overwrite) { Assert.Check(capacity > 0); Assert.Check(stride > 0); // fixedSize means we are allocating the memory for the collection header and the items in it as one block var alignment = AllocHelper.GetAlignmentForArrayElement(stride); // align header size to the elements alignment var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeRingBuffer), alignment); var sizeOfBuffer = stride * capacity; // allocate memory for list and array with the correct alignment var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeOfBuffer, alignment); // grab header ptr var ring = (UnsafeRingBuffer *)ptr; // initialize fixed buffer from same block of memory as the collection, offset by sizeOfHeader UnsafeBuffer.InitFixed(&ring->_items, (byte *)ptr + sizeOfHeader, capacity, stride); // initialize count to 0 ring->_count = 0; ring->_overwrite = overwrite; return(ring); }
public static UnsafeHashSet *Allocate(int capacity, int valStride, bool fixedSize = false) { var entryStride = sizeof(UnsafeHashCollection.Entry); // round capacity up to next prime capacity = UnsafeHashCollection.GetNextPrime(capacity); // this has to be true Assert.Check(entryStride == 16); var valAlignment = AllocHelper.GetAlignmentForArrayElement(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 = AllocHelper.RoundUpToAlignment(valStride, alignment); entryStride = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashCollection.Entry), alignment); // dictionary ptr UnsafeHashSet *set; if (fixedSize) { var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashSet), alignment); var sizeOfBucketsBuffer = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHashCollection.Entry * *) * capacity, alignment); var sizeofEntriesBuffer = (entryStride + valStride) * capacity; // allocate memory var ptr = AllocHelper.MallocAndClear(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 = AllocHelper.MallocAndClear <UnsafeHashSet>(); set->_collection.Buckets = (UnsafeHashCollection.Entry * *)AllocHelper.MallocAndClear(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; return(set); }
public static void InitDynamic(UnsafeBuffer *buffer, int length, int stride) { Assert.Check(buffer != null); Assert.Check(length > 0); Assert.Check(stride > 0); buffer->Ptr = AllocHelper.MallocAndClear(length * stride, AllocHelper.GetAlignmentForArrayElement(stride)); buffer->Length = length; buffer->Stride = stride; buffer->Dynamic = true; }
static void Expand(UnsafeHashCollection *collection) { Assert.Check(collection->Entries.Dynamic); var capacity = GetNextPrime(collection->Entries.Length); Assert.Check(capacity >= collection->Entries.Length); var newBuckets = (Entry **)AllocHelper.MallocAndClear(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 AllocHelper.Free(collection->Buckets); UnsafeBuffer.Free(&collection->Entries); // new storage collection->Buckets = newBuckets; collection->Entries = newEntries; }
public static UnsafeOrderedSet *Allocate(int capacity, int valStride, bool fixedSize = false) { var entryStride = sizeof(UnsafeOrderedCollection.Entry); var valAlignment = AllocHelper.GetAlignmentForArrayElement(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 = AllocHelper.RoundUpToAlignment(valStride, alignment); entryStride = AllocHelper.RoundUpToAlignment(entryStride, alignment); // dictionary ptr UnsafeOrderedSet *set; if (fixedSize) { var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeOrderedSet), alignment); var sizeofEntriesBuffer = (entryStride + valStride) * capacity; // allocate memory var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeofEntriesBuffer, alignment); // start of memory is the set itself set = (UnsafeOrderedSet *)ptr; // initialize fixed buffer UnsafeBuffer.InitFixed(&set->_collection.Entries, (byte *)ptr + sizeOfHeader, capacity, entryStride + valStride); } else { // allocate set separately set = AllocHelper.MallocAndClear <UnsafeOrderedSet>(); // init dynamic buffer UnsafeBuffer.InitDynamic(&set->_collection.Entries, capacity, entryStride + valStride); } set->_collection.FreeCount = 0; set->_collection.UsedCount = 0; set->_collection.KeyOffset = entryStride; return(set); }
public static UnsafeStack *Allocate(int capacity, int stride, bool fixedSize = false) { Assert.Check(capacity > 0); Assert.Check(stride > 0); 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 = AllocHelper.GetAlignmentForArrayElement(stride); // align stack header size to the elements alignment var sizeOfStack = AllocHelper.RoundUpToAlignment(sizeof(UnsafeStack), alignment); var sizeOfArray = stride * capacity; // allocate memory for stack and array with the correct alignment var ptr = AllocHelper.MallocAndClear(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 = AllocHelper.MallocAndClear <UnsafeStack>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&stack->_items, capacity, stride); } // just safety, make sure count is 0 stack->_count = 0; return(stack); }
public static UnsafeHeapMax *Allocate(int capacity, int keyStride, int valStride, bool fixedSize = false) { capacity += 1; // get alignment for key/val var keyAlignment = AllocHelper.GetAlignmentForArrayElement(keyStride); var valAlignment = AllocHelper.GetAlignmentForArrayElement(valStride); // pick the max one as our alignment var alignment = Math.Max(keyAlignment, valAlignment); // align sizes to their respective alignments keyStride = AllocHelper.RoundUpToAlignment(keyStride, alignment); valStride = AllocHelper.RoundUpToAlignment(valStride, alignment); UnsafeHeapMax *heap; if (fixedSize) { var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeHeapMax), alignment); var sizeOfBuffer = (keyStride + valStride) * capacity; var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeOfBuffer, alignment); // heap pointer heap = (UnsafeHeapMax *)ptr; // initialize our fixed buffer UnsafeBuffer.InitFixed(&heap->_items, (byte *)ptr + sizeOfHeader, capacity, keyStride + valStride); } else { heap = AllocHelper.MallocAndClear <UnsafeHeapMax>(); // dynamic buffer (separate memory) UnsafeBuffer.InitDynamic(&heap->_items, capacity, keyStride + valStride); } heap->_count = 1; heap->_keyStride = keyStride; return(heap); }
public static UnsafeQueue *Allocate(int capacity, int stride, bool fixedSize = false) { Assert.Check(capacity > 0); Assert.Check(stride > 0); 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 = AllocHelper.GetAlignmentForArrayElement(stride); var sizeOfQueue = AllocHelper.RoundUpToAlignment(sizeof(UnsafeQueue), alignment); var sizeOfArray = stride * capacity; var ptr = AllocHelper.MallocAndClear(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 = AllocHelper.MallocAndClear <UnsafeQueue>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&queue->_items, capacity, stride); } queue->_head = 0; queue->_tail = 0; queue->_count = 0; return(queue); }
public static UnsafeBitSet *Alloc(int size) { if (size < 1) { throw new InvalidOperationException(SET_SIZE_LESS_THAN_ONE); } // round to WORD_BIT_SIZE alignment, as we operate on the bitset using WORD_SIZE size = AllocHelper.RoundUpToAlignment(size, WORD_SIZE_BITS); var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeBitSet), WORD_SIZE); var sizeOfBuffer = size / 8; // 8 bits per byte var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeOfBuffer); var set = (UnsafeBitSet *)ptr; // set bit capacity set->_sizeBits = size; set->_sizeBuckets = size / WORD_SIZE_BITS; set->_bits = (ulong *)((byte *)ptr + sizeOfHeader); return(set); }
public static UnsafeList *Allocate(int capacity, int stride, bool fixedSize = false) { Assert.Check(capacity > 0); Assert.Check(stride > 0); 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 = AllocHelper.GetAlignmentForArrayElement(stride); // align header size to the elements alignment var sizeOfHeader = AllocHelper.RoundUpToAlignment(sizeof(UnsafeList), alignment); var sizeOfBuffer = stride * capacity; // allocate memory for list and array with the correct alignment var ptr = AllocHelper.MallocAndClear(sizeOfHeader + sizeOfBuffer, alignment); // 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 = AllocHelper.MallocAndClear <UnsafeList>(); // initialize dynamic buffer with separate memory UnsafeBuffer.InitDynamic(&list->_items, capacity, stride); } list->_count = 0; return(list); }
internal static UnsafeOrderedCollection *Allocate(int capacity, int valStride) { var entryStride = sizeof(Entry); var valAlignment = AllocHelper.GetAlignmentForArrayElement(valStride); // alignment we need is max of the two alignments var alignment = Math.Max(Entry.ALIGNMENT, valAlignment); // calculate strides for all elements valStride = AllocHelper.RoundUpToAlignment(valStride, alignment); entryStride = AllocHelper.RoundUpToAlignment(entryStride, alignment); // allocate dict, buckets and entries buffer separately var collection = AllocHelper.MallocAndClear <UnsafeOrderedCollection>(); // init dynamic buffer UnsafeBuffer.InitDynamic(&collection->Entries, capacity, entryStride + valStride); collection->FreeCount = 0; collection->UsedCount = 0; collection->KeyOffset = entryStride; return(collection); }