/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System.Collections.Generic; namespace wasSharp.Collections.Generic { /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// A circular queue implementation based on linked lists. /// /// the type of value to store public class CircularQueue { private readonly LinkedList Store = new LinkedList(); private readonly object SyncRoot = new object(); private LinkedListNode CurrentNode; public CircularQueue() { } public CircularQueue(IEnumerable items) { Enqueue(items); } public CircularQueue(CircularQueue queue) { lock (SyncRoot) { lock (queue.SyncRoot) { foreach (var item in queue.Items) { Store.AddLast(item); } if (CurrentNode == null) CurrentNode = Store.First; } } } public int Count { get { lock (SyncRoot) { return Store.Count; } } } public bool IsEmpty { get { lock (SyncRoot) { return Store.Count.Equals(0); } } } private T GetNext { get { lock (SyncRoot) { if (CurrentNode == null) return default(T); var value = CurrentNode.Value; switch (CurrentNode.Next != null) { case true: CurrentNode = CurrentNode.Next; break; default: CurrentNode = Store.First; break; } return value; } } } public IEnumerable Items { get { lock (SyncRoot) { if (CurrentNode == null) yield break; var node = CurrentNode; do { yield return node.Value; node = node.Next; } while (node != null); } } } public void Enqueue(IEnumerable items) { lock (SyncRoot) { foreach (var i in items) Store.AddLast(i); if (CurrentNode == null) CurrentNode = Store.First; } } public void Enqueue(T item) { lock (SyncRoot) { Store.AddLast(item); if (CurrentNode == null) CurrentNode = Store.First; } } public T Dequeue() { lock (SyncRoot) { return GetNext; } } public IEnumerable Dequeue(int count = 1) { if (count <= 0) yield break; lock (SyncRoot) { if (CurrentNode == null) yield break; do { yield return GetNext; } while (--count != 0); } } public void Clear() { lock (SyncRoot) { Store.Clear(); CurrentNode = null; } } public bool Contains(T item) { lock (SyncRoot) { return Store.Contains(item); } } public void CopyTo(T[] array, int arrayIndex) { lock (SyncRoot) { Store.CopyTo(array, arrayIndex); } } public bool Remove(T item) { lock (SyncRoot) { var node = Store.Find(item); if (node == null) return false; if (CurrentNode.Equals(node)) { switch (node.Next != null) { case true: CurrentNode = node.Next; break; default: CurrentNode = Store.First; break; } } Store.Remove(node); return true; } } public void RemoveAll(IEnumerable items) { var itemSet = new HashSet(items); lock (SyncRoot) { var node = CurrentNode; do { var next = node.Next; if (itemSet.Contains(node.Value)) { switch (next != null) { case true: CurrentNode = next; break; default: CurrentNode = Store.First; break; } Store.Remove(node); } node = next; } while (node != null); } } } }