// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System; using System.Collections; using System.Collections.Generic; namespace osu.Game.Utils { /// /// An indexed queue with limited capacity. /// Respects first-in-first-out insertion order. /// public class LimitedCapacityQueue : IEnumerable { /// /// The number of elements in the queue. /// public int Count { get; private set; } /// /// Whether the queue is full (adding any new items will cause removing existing ones). /// public bool Full => Count == capacity; private readonly T[] array; private readonly int capacity; // Markers tracking the queue's first and last element. private int start, end; /// /// Constructs a new /// /// The number of items the queue can hold. public LimitedCapacityQueue(int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity)); this.capacity = capacity; array = new T[capacity]; Clear(); } /// /// Removes all elements from the . /// public void Clear() { start = 0; end = -1; Count = 0; } /// /// Removes an item from the front of the . /// /// The item removed from the front of the queue. public T Dequeue() { if (Count == 0) throw new InvalidOperationException("Queue is empty."); var result = array[start]; start = (start + 1) % capacity; Count--; return result; } /// /// Adds an item to the back of the . /// If the queue is holding elements at the point of addition, /// the item at the front of the queue will be removed. /// /// The item to be added to the back of the queue. public void Enqueue(T item) { end = (end + 1) % capacity; if (Count == capacity) start = (start + 1) % capacity; else Count++; array[end] = item; } /// /// Retrieves the item at the given index in the queue. /// /// /// The index of the item to retrieve. /// The item with index 0 is at the front of the queue /// (it was added the earliest). /// public T this[int index] { get { if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException(nameof(index)); return array[(start + index) % capacity]; } } /// /// Enumerates the queue from its start to its end. /// public IEnumerator GetEnumerator() { if (Count == 0) yield break; for (int i = 0; i < Count; i++) yield return array[(start + i) % capacity]; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }