using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; namespace squirrowse.web.Common { public class ConcurrentFixedSizeQueue : IProducerConsumerCollection, IReadOnlyCollection, ICollection { private readonly ConcurrentQueue m_concurrentQueue; private readonly int m_maxSize; public ConcurrentFixedSizeQueue(int maxSize) : this(Array.Empty(), maxSize) { } public ConcurrentFixedSizeQueue(IEnumerable initialCollection, int maxSize) { if (initialCollection == null) throw new ArgumentNullException(nameof(initialCollection)); m_concurrentQueue = new ConcurrentQueue(initialCollection); m_maxSize = maxSize; } public bool IsEmpty => m_concurrentQueue.IsEmpty; public int Count => m_concurrentQueue.Count; public void CopyTo(T[] array, int index) { m_concurrentQueue.CopyTo(array, index); } public T[] ToArray() { return m_concurrentQueue.ToArray(); } public IEnumerator GetEnumerator() { return m_concurrentQueue.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } // Explicit ICollection implementations. void ICollection.CopyTo(Array array, int index) { ((ICollection) m_concurrentQueue).CopyTo(array, index); } object ICollection.SyncRoot => ((ICollection) m_concurrentQueue).SyncRoot; bool ICollection.IsSynchronized => ((ICollection) m_concurrentQueue).IsSynchronized; // Explicit IProducerConsumerCollection implementations. bool IProducerConsumerCollection.TryAdd(T item) { return ((IProducerConsumerCollection) m_concurrentQueue).TryAdd(item); } bool IProducerConsumerCollection.TryTake(out T item) { return ((IProducerConsumerCollection) m_concurrentQueue).TryTake(out item); } public void Enqueue(T item) { m_concurrentQueue.Enqueue(item); if (m_concurrentQueue.Count > m_maxSize) m_concurrentQueue.TryDequeue(out var result); } public void TryPeek(out T result) { m_concurrentQueue.TryPeek(out result); } public bool TryDequeue(out T result) { return m_concurrentQueue.TryDequeue(out result); } public override int GetHashCode() { return m_concurrentQueue.GetHashCode(); } public override bool Equals(object obj) { return m_concurrentQueue.Equals(obj); } public override string ToString() { return m_concurrentQueue.ToString(); } } }