using System; using System.Collections.Generic; namespace ZeroLevel.Services.Collections { public sealed class FixSizeQueue : IFixSizeQueue { private readonly T[] _array; private long _nextIndex; private long _startIndex; private long _count; private readonly object _accessLocker = new object(); public FixSizeQueue(long capacity) { if (capacity <= 0) { capacity = 1024; } _array = new T[capacity]; _nextIndex = 0; _count = 0; } /// /// If count is limited when intem adding, oldest item replace with new item /// public void Push(T item) { lock (_accessLocker) { _array[_nextIndex] = item; _nextIndex = (_nextIndex + 1) % _array.Length; if (_count < _array.Length) { _count++; } else { _startIndex = (_startIndex + 1) % _array.Length; } } } public bool Equals(T x, T y) { if (x == null && y == null!) return true; if (x == null || y == null!) return false; if ((object)x == (object)y) return true; if (ReferenceEquals(x, y)) return true; return x.Equals(y); } public bool Contains(T item, IComparer comparer = null!) { lock (_accessLocker) { Func eq_func; if (comparer == null!) { eq_func = Equals; } else { eq_func = (x, y) => comparer.Compare(x, y) == 0; } var cursor = _startIndex; if (_count > 0) { do { if (eq_func(_array[cursor], item)) return true; cursor = (cursor + 1) % _array.Length; } while (cursor != _nextIndex); } } return false; } public long Count { get { return _count; } } public bool TryTake(out T t) { lock (_accessLocker) { if (_count > 0) { t = _array[_startIndex]; _array[_startIndex] = default(T)!; _startIndex = (_startIndex + 1) % _array.Length; _count--; return true; } } t = default(T)!; return false; } public T Take() { T ret; lock (_accessLocker) { if (_count > 0) { ret = _array[_startIndex]; _array[_startIndex] = default(T)!; _startIndex = (_startIndex + 1) % _array.Length; _count--; return ret; } } throw new System.Exception("Collection is empty"); } public IEnumerable Dump() { lock (_accessLocker) { var cursor = _startIndex; if (_count > 0) { do { yield return _array[cursor]; cursor = (cursor + 1) % _array.Length; } while (cursor != _nextIndex); } } } } }