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
}
}