/// <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); }
public static void Clear(UnsafeSPSCQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); queue->_headAndTail = new HeadAndTail(); }
public static void Clear(UnsafeMPSCQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); queue->_headAndTail = new HeadAndTail(); // Initialize the sequence number for each slot. // This is used to synchronize between consumer and producer threads. var offset = queue->_slotOffset; var items = queue->_items; for (int i = 0; i < queue->_items.Length; i++) { *(int *)items.Element(i, offset) = i; } }