コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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;
        }
コード例 #5
0
        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;
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        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);
        }