private static void SplitQueue(UnsafeQueue *q) { //Wrap tail back to 0 for (int i = 0; i < 5; i++) { UnsafeQueue.Enqueue(q, 111); } //First half for (int i = 0; i < 5; i++) { UnsafeQueue.Enqueue(q, i); } //Move head by 5 for (int i = 0; i < 5; i++) { UnsafeQueue.Dequeue <int>(q); } //Second half (head and tail are now both 5) for (int i = 5; i < 10; i++) { UnsafeQueue.Enqueue(q, i); } //Circular buffer now "ends" in the middle of the underlying array }
public static void Enqueue <T>(UnsafeQueue *queue, T item) where T : unmanaged { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); var count = queue->_count; var items = queue->_items; if (count == items.Length) { if (items.Dynamic == 1) { Expand(queue, items.Length * 2); // re-assign items after capacity expanded items = queue->_items; } else { throw new InvalidOperationException(QUEUE_FIXED_SIZE_FULL); } } var tail = queue->_tail; *(T *)UnsafeBuffer.Element(items.Ptr, tail, items.Stride) = item; // increment count and head index queue->_count = (count + 1); queue->_tail = (tail + 1) % items.Length; }
public static void Enqueue <T>(UnsafeQueue *queue, T item) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); var count = queue->_count; var items = queue->_items; if (count == items.Length) { if (items.Dynamic == 1) { Expand(queue, items.Length * 2); // re-assign items after capacity expanded items = queue->_items; } else { throw new InvalidOperationException(ThrowHelper.InvalidOperation_CollectionFull); } } var tail = queue->_tail; *items.Element <T>(tail) = item; // increment count and head index queue->_count++; MoveNext(items.Length, ref queue->_tail); }
public static void CopyTo <T>(UnsafeQueue *queue, void *destination, int destinationIndex) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); UDebug.Assert(destination != null); UDebug.Assert(destinationIndex > -1); int numToCopy = queue->_count; if (numToCopy == 0) { return; } int bufferLength = queue->_items.Length; int head = queue->_head; int firstPart = Math.Min(bufferLength - head, numToCopy); UnsafeBuffer.CopyTo <T>(queue->_items, head, destination, destinationIndex, firstPart); numToCopy -= firstPart; if (numToCopy > 0) { UnsafeBuffer.CopyTo <T>(queue->_items, 0, destination, destinationIndex + bufferLength - head, numToCopy); } }
public static void Clear(UnsafeQueue *queue) { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); queue->_head = 0; queue->_tail = 0; }
public static UnsafeList.Enumerator <T> GetEnumerator <T>(UnsafeQueue *queue) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); return(new UnsafeList.Enumerator <T>(queue->_items, queue->_head, queue->_count)); }
public static void Clear(UnsafeQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); queue->_head = 0; queue->_tail = 0; queue->_count = 0; }
public static bool TryEnqueue <T>(UnsafeQueue *queue, T item) where T : unmanaged { if (queue->_count == queue->_items.Length && queue->_items.Dynamic == 0) { return(false); } Enqueue <T>(queue, item); return(true); }
public static T Peek <T>(UnsafeQueue *queue) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); if (queue->_count == 0) { throw new InvalidOperationException(ThrowHelper.InvalidOperation_EmptyQueue); } return(*queue->_items.Element <T>(queue->_head)); }
public static bool TryPeek <T>(UnsafeQueue *queue, out T result) where T : unmanaged { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); if (queue->_count == 0) { result = default; return(false); } result = *PeekPtr <T>(queue); return(true); }
public static T *PeekPtr <T>(UnsafeQueue *queue) where T : unmanaged { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); if (queue->_count == 0) { throw new InvalidOperationException(QUEUE_EMPTY); } var items = queue->_items; return((T *)UnsafeBuffer.Element(items.Ptr, queue->_head, items.Stride)); }
public static bool TryPeek <T>(UnsafeQueue *queue, out T result) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); if (queue->_count == 0) { result = default; return(false); } //Don't call Peek as this would perform the same check twice! result = *queue->_items.Element <T>(queue->_head); return(true); }
public static void Free(UnsafeQueue *queue) { if (queue == null) { return; } // not fixed, we need to free items separtely if (queue->_items.Dynamic == 1) { UnsafeBuffer.Free(&queue->_items); } // clear queue memory (just in case) *queue = default; // free queue memory, if this is a fixed queue it frees the items memory at the same time Native.Free(queue); }
// expand algorithm from first answer here: https://codereview.stackexchange.com/questions/129819/queue-resizing-array-implementation static void Expand(UnsafeQueue *queue, int capacity) { Assert.Check(capacity > 0); // queue has to be dynamic and capacity we're going to have to be larger Assert.Check(queue->_items.Dynamic == 1); Assert.Check(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; }
public static T Dequeue <T>(UnsafeQueue *queue) where T : unmanaged { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); var count = queue->_count; if (count == 0) { throw new InvalidOperationException(QUEUE_EMPTY); } var head = queue->_head; var items = queue->_items; // grab result T result = *(T *)UnsafeBuffer.Element(items.Ptr, head, items.Stride); // decrement count and tail index queue->_count = (count - 1); queue->_head = (head + 1) % items.Length; return(result); }
public static bool TryDequeue <T>(UnsafeQueue *queue, out T result) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); if (queue->_count == 0) { result = default; return(false); } var head = queue->_head; var items = queue->_items; // grab result result = *items.Element <T>(head); // decrement count and head index queue->_count--; MoveNext(items.Length, ref queue->_head); return(true); }
public static bool Contains <T>(UnsafeQueue *queue, T item) where T : unmanaged, IEquatable <T> { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); int count = queue->_count; int head = queue->_head; int tail = queue->_tail; if (count == 0) { return(false); } if (head < tail) { return(UnsafeBuffer.IndexOf(queue->_items, item, head, count) > -1); } return(UnsafeBuffer.IndexOf(queue->_items, item, head, queue->_items.Length - head) > -1 || UnsafeBuffer.IndexOf(queue->_items, item, 0, tail) > -1); }
public static T Dequeue <T>(UnsafeQueue *queue) where T : unmanaged { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle); var count = queue->_count; if (count == 0) { throw new InvalidOperationException(ThrowHelper.InvalidOperation_EmptyQueue); } var head = queue->_head; var items = queue->_items; // grab result T result = *items.Element <T>(head); // decrement count and head index queue->_count--; MoveNext(items.Length, ref queue->_head); return(result); }
public NativeQueue(int capacity) { m_inner = UnsafeQueue.Allocate <T>(capacity, false); }
public static UnsafeList.Iterator <T> GetIterator <T>(UnsafeQueue *queue) where T : unmanaged { return(new UnsafeList.Iterator <T>(queue->_items, queue->_head, queue->_count)); }
public static int GetCapacity(UnsafeQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); return(queue->_items.Length); }
public static T Peek <T>(UnsafeQueue *queue) where T : unmanaged { return(*PeekPtr <T>(queue)); }
public static int GetCount(UnsafeQueue *queue) { UDebug.Assert(queue != null); UDebug.Assert(queue->_items.Ptr != null); return(queue->_count); }
public static bool IsFixedSize(UnsafeQueue *queue) { Assert.Check(queue != null); return(queue->_items.Dynamic == 0); }
public static int Count(UnsafeQueue *queue) { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); return(queue->_count); }
public static int Capacity(UnsafeQueue *queue) { Assert.Check(queue != null); Assert.Check(queue->_items.Ptr != null); return(queue->_items.Length); }
public NativeQueue(int capacity, bool fixedSize) { m_inner = UnsafeQueue.Allocate <T>(capacity, fixedSize); }