Beispiel #1
0
        /// <summary>
        /// Allocates a new SPSCRingbuffer. Capacity will be set to a power of 2.
        /// </summary>
        public static UnsafeSPSCQueue *Allocate <T>(int capacity) where T : unmanaged
        {
            if (capacity < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity)));
            }

            // Requires one extra element to distinguish between empty and full queue.
            capacity++;

            int stride = sizeof(T);

            var alignment   = Memory.GetAlignment(stride);
            var sizeOfQueue = Memory.RoundToAlignment(sizeof(UnsafeSPSCQueue), alignment);
            var sizeOfArray = stride * capacity;

            var ptr = Memory.MallocAndZero(sizeOfQueue + sizeOfArray, alignment);

            UnsafeSPSCQueue *queue = (UnsafeSPSCQueue *)ptr;

            // initialize fixed buffer from same block of memory as the stack
            UnsafeBuffer.InitFixed(&queue->_items, (byte *)ptr + sizeOfQueue, capacity, stride);

            queue->_headAndTail = new HeadAndTail();
            queue->_typeHandle  = typeof(T).TypeHandle.Value;

            return(queue);
        }
Beispiel #2
0
        public static UnsafeRingBuffer *Allocate <T>(int capacity, bool overwrite) where T : unmanaged
        {
            if (capacity < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity)));
            }

            int stride = sizeof(T);

            // fixedSize means we are allocating the memory for the collection header and the items in it as one block
            var alignment = Memory.GetAlignment(stride);

            // align header size to the elements alignment
            var sizeOfHeader = Memory.RoundToAlignment(sizeof(UnsafeRingBuffer), alignment);
            var sizeOfBuffer = stride * capacity;

            // allocate memory for list and array with the correct alignment
            var ptr = Memory.MallocAndZero(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 ? 1 : 0;
            ring->_typeHandle = typeof(T).TypeHandle.Value;
            return(ring);
        }
Beispiel #3
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);
        }
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        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);
        }
        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);
        }
        int          _slotOffset; // Readonly

        /// <summary>
        /// Allocates a new SPSCRingbuffer. Capacity will be set to a power of 2.
        /// </summary>
        public static UnsafeMPSCQueue *Allocate <T>(int capacity) where T : unmanaged
        {
            if (capacity < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(capacity), string.Format(ThrowHelper.ArgumentOutOfRange_MustBePositive, nameof(capacity)));
            }

            capacity = Memory.RoundUpToPowerOf2(capacity);

            // Required to get the memory size of the Slot + Value
            int slotStride = Marshal.SizeOf(new QueueSlot <T>());
            int slotAlign  = Memory.GetMaxAlignment(sizeof(T), sizeof(int));
            int slotOffset = Memory.RoundToAlignment(sizeof(T), slotAlign);

            int alignment = Memory.GetAlignment(slotStride);

            var sizeOfQueue = Memory.RoundToAlignment(sizeof(UnsafeMPSCQueue), alignment);
            var sizeOfArray = slotStride * capacity;

            var ptr = Memory.MallocAndZero(sizeOfQueue + sizeOfArray, alignment);

            UnsafeMPSCQueue *queue = (UnsafeMPSCQueue *)ptr;

            // initialize fixed buffer from same block of memory as the stack
            UnsafeBuffer.InitFixed(&queue->_items, (byte *)ptr + sizeOfQueue, capacity, slotStride);

            // Read-only values
            queue->_mask       = capacity - 1;
            queue->_slotOffset = slotOffset;
            queue->_typeHandle = typeof(T).TypeHandle.Value;

            // Reset the queue for use.
            Clear(queue);

            return(queue);
        }
Beispiel #10
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);
        }