/Collections/Generic/CircularQueue.cs |
@@ -0,0 +1,232 @@ |
/////////////////////////////////////////////////////////////////////////// |
// 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 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// A circular queue implementation based on linked lists. |
/// </summary> |
/// <typeparam name="T">the type of value to store</typeparam> |
public class CircularQueue<T> |
{ |
private readonly LinkedList<T> Store = new LinkedList<T>(); |
private LinkedListNode<T> CurrentNode; |
|
private readonly object SyncRoot = new object(); |
|
public CircularQueue() |
{ |
} |
|
public CircularQueue(IEnumerable<T> items) |
{ |
Enqueue(items); |
} |
|
public CircularQueue(CircularQueue<T> 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; |
} |
} |
} |
|
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<T> 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<T> 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<T> 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<T> items) |
{ |
var itemSet = new HashSet<T>(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); |
} |
} |
} |
} |