using System; using System.Collections; using System.Collections.Generic; using System.Linq; using ICD.Common.Properties; namespace ICD.Common.Utils.Collections { /// /// ScrollQueue is a queue that never exceeds a predefined length. Old items /// are removed as new items are added. /// /// public sealed class ScrollQueue : IEnumerable, ICollection { private readonly LinkedList m_Collection; private int m_MaxSize; private readonly SafeCriticalSection m_CollectionLock; #region Properties /// /// Gets/sets the maximum size of the queue. /// [PublicAPI] public int MaxSize { get { return m_MaxSize; } set { if (value == m_MaxSize) return; m_MaxSize = value; Trim(); } } /// /// Gets the number of items in the collection. /// public int Count { get { return m_CollectionLock.Execute(() => m_Collection.Count); } } /// /// The IsSynchronized Boolean property returns True if the /// collection is designed to be thread safe; otherwise, it returns False. /// public bool IsSynchronized { get { return true; } } /// /// The SyncRoot property returns an object, which is used for synchronizing /// the collection. This returns the instance of the object or returns the /// SyncRoot of other collections if the collection contains other collections. /// public object SyncRoot { get { return this; } } #endregion /// /// Constructor. /// /// public ScrollQueue(int maxSize) { m_CollectionLock = new SafeCriticalSection(); m_Collection = new LinkedList(); MaxSize = maxSize; } #region Queue Methods /// /// Clears all items from the queue. /// public void Clear() { m_CollectionLock.Execute(() => m_Collection.Clear()); } /// /// Appends the item to the queue, trims old items that exceed max length. /// /// [PublicAPI] public void Enqueue(TContents item) { m_CollectionLock.Execute(() => m_Collection.AddLast(item)); Trim(); } /// /// Removes the oldest item from the queue. /// /// [PublicAPI] public TContents Dequeue() { m_CollectionLock.Enter(); try { TContents output = m_Collection.First.Value; m_Collection.RemoveFirst(); return output; } finally { m_CollectionLock.Leave(); } } /// /// Returns the oldest item in the queue. /// /// [PublicAPI] public TContents Peek() { return m_CollectionLock.Execute(() => m_Collection.First.Value); } #endregion #region Implemented Methods IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { return m_CollectionLock.Execute(() => m_Collection.ToList().GetEnumerator()); } void ICollection.CopyTo(Array myArr, int index) { m_CollectionLock.Enter(); try { foreach (TContents item in m_Collection) { myArr.SetValue(item, index); index++; } } finally { m_CollectionLock.Leave(); } } #endregion #region Private Methods /// /// Removes items that fall outside of the max size. /// private void Trim() { m_CollectionLock.Enter(); try { while (Count > MaxSize) m_Collection.RemoveFirst(); } finally { m_CollectionLock.Leave(); } } #endregion } }