From bfd3d0cce978c77d4bfa7bbe1a15262e4cc23c80 Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Sat, 10 Apr 2021 01:16:54 +1000 Subject: [PATCH] Implement custom enumerator for ReverseQueue to avoid allocations --- .../Rulesets/Difficulty/Utils/ReverseQueue.cs | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs index f104b8105a..57db9df3ca 100644 --- a/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs +++ b/osu.Game/Rulesets/Difficulty/Utils/ReverseQueue.cs @@ -101,12 +101,33 @@ namespace osu.Game.Rulesets.Difficulty.Utils /// /// Returns an enumerator which enumerates items in the starting from the most recently enqueued item. /// - public IEnumerator GetEnumerator() - { - for (int i = Count - 1; i >= 0; i--) - yield return items[(start + i) % capacity]; - } + public IEnumerator GetEnumerator() => new Enumerator(this); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator + { + private ReverseQueue reverseQueue; + private int currentIndex; + + internal Enumerator(ReverseQueue reverseQueue) + { + this.reverseQueue = reverseQueue; + currentIndex = -1; // The first MoveNext() should bring the iterator to 0 + } + + public bool MoveNext() => ++currentIndex < reverseQueue.Count; + + public void Reset() => currentIndex = -1; + + public readonly T Current => reverseQueue[currentIndex]; + + readonly object IEnumerator.Current => Current; + + public void Dispose() + { + reverseQueue = null; + } + } } }