diff --git a/Nuclex.Support (PC).csproj b/Nuclex.Support (PC).csproj index 3949a0d..f5b56eb 100644 --- a/Nuclex.Support (PC).csproj +++ b/Nuclex.Support (PC).csproj @@ -65,6 +65,10 @@ + + false + UnintrusivePriorityQueue + false Parentable @@ -77,6 +81,11 @@ false PriorityQueue + + false + PriorityQueue.Test + PriorityQueue.cs + false RingMemoryStream @@ -87,6 +96,11 @@ RingMemoryStream.Test RingMemoryStream.cs + + false + UnintrusivePriorityQueue.Test + UnintrusivePriorityQueue.cs + false BinarySerializer.Test diff --git a/Source/Collections/ParentingCollection.cs b/Source/Collections/ParentingCollection.cs index 9fe4e65..9d0cd1f 100644 --- a/Source/Collections/ParentingCollection.cs +++ b/Source/Collections/ParentingCollection.cs @@ -14,15 +14,10 @@ namespace Nuclex.Support.Collections { /// /// Type of the parent object to assign to items /// Type of the items being managed in the collection - public class ParentingCollection : Collection, IDisposable + public class ParentingCollection : Collection where ItemType : Parentable where ParentType : class { - /// Called when the object is garbage-collected - ~ParentingCollection() { - Dispose(false); // called from GC - } - /// Reparents all elements in the collection /// New parent to take ownership of the items protected void Reparent(ParentType parent) { @@ -32,37 +27,6 @@ namespace Nuclex.Support.Collections { base[index].SetParent(parent); } - /// Called when the asset needs to release its resources - /// - /// Whether the mehod has been called from user code. If this argument - /// is false, the object is being disposed by the garbage collector and - /// it mustn't access other objects (including the attempt to Dispose() them) - /// as these might have already been destroyed by the GC. - /// - protected virtual void Dispose(bool calledByUser) { - - // Only destroy the other resources when we're not being called from - // the garbage collector, otherwise we'd risk accessing objects that - // have already been disposed - if(calledByUser) { - - // Have the items do their cleanup work - Reparent(null); - - // Dispose of all the items in the collection - foreach(ItemType item in this) { - IDisposable disposable = item as IDisposable; - if(disposable != null) - disposable.Dispose(); - } - - // Remove all items from the collection - base.ClearItems(); - - } - - } - /// Clears all elements from the collection protected override void ClearItems() { for(int index = 0; index < Count; ++index) @@ -94,9 +58,32 @@ namespace Nuclex.Support.Collections { item.SetParent(this.parent); } - /// Release all resources owned by the instance explicitely - public void Dispose() { - Dispose(true); // Called by user + /// Disposes the collection and optionally all items contained therein + /// Whether to try calling Dispose() on all items + /// + /// This method is intended to support collections that need to dispose their + /// items. The ParentingCollection will first detach all items from the parent + /// object and them call Dispose() on any item that implements IDisposable. + /// + protected void InternalDispose(bool disposeItems) { + + if(disposeItems) { + + // Have the items do their cleanup work + Reparent(null); + + // Dispose of all the items in the collection that implement IDisposable + foreach(ItemType item in this) { + IDisposable disposable = item as IDisposable; + if(disposable != null) + disposable.Dispose(); + } + + } + + // Remove all items from the collection + base.ClearItems(); + } /// Parent this collection currently belongs to diff --git a/Source/Collections/PriorityQueue.Test.cs b/Source/Collections/PriorityQueue.Test.cs new file mode 100644 index 0000000..ccbb247 --- /dev/null +++ b/Source/Collections/PriorityQueue.Test.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; + +#if UNITTEST + +using NUnit.Framework; + +namespace Nuclex.Support.Collections { + + /// Unit Test for the priority queue class + [TestFixture] + public class PriorityQueueTest { + + private class FloatComparer : IComparer { + + public int Compare(float left, float right) { + return Math.Sign(left - right); + } + + public static readonly FloatComparer Default = new FloatComparer(); + + } + + /// Tests to ensure the count property is properly updated + [Test] + public void TestCount() { + PriorityQueue testQueue = new PriorityQueue(FloatComparer.Default); + + Assert.AreEqual(0, testQueue.Count); + testQueue.Enqueue(12.34f); + Assert.AreEqual(1, testQueue.Count); + testQueue.Enqueue(56.78f); + Assert.AreEqual(2, testQueue.Count); + testQueue.Dequeue(); + Assert.AreEqual(1, testQueue.Count); + testQueue.Enqueue(9.0f); + Assert.AreEqual(2, testQueue.Count); + testQueue.Clear(); + Assert.AreEqual(0, testQueue.Count); + } + + /// Tests to ensure that the priority collection actually sorts items + [Test] + public void TestOrdering() { + PriorityQueue testQueue = new PriorityQueue(FloatComparer.Default); + + testQueue.Enqueue(1.0f); + testQueue.Enqueue(9.0f); + testQueue.Enqueue(2.0f); + testQueue.Enqueue(8.0f); + testQueue.Enqueue(3.0f); + testQueue.Enqueue(7.0f); + testQueue.Enqueue(4.0f); + testQueue.Enqueue(6.0f); + testQueue.Enqueue(5.0f); + + Assert.AreEqual(9.0f, testQueue.Dequeue()); + Assert.AreEqual(8.0f, testQueue.Dequeue()); + Assert.AreEqual(7.0f, testQueue.Dequeue()); + Assert.AreEqual(6.0f, testQueue.Dequeue()); + Assert.AreEqual(5.0f, testQueue.Dequeue()); + Assert.AreEqual(4.0f, testQueue.Dequeue()); + Assert.AreEqual(3.0f, testQueue.Dequeue()); + Assert.AreEqual(2.0f, testQueue.Dequeue()); + Assert.AreEqual(1.0f, testQueue.Dequeue()); + } + + } + +} // namespace Nuclex.Support.Collections + +#endif // UNITTEST diff --git a/Source/Collections/PriorityQueue.cs b/Source/Collections/PriorityQueue.cs index f61d845..fade547 100644 --- a/Source/Collections/PriorityQueue.cs +++ b/Source/Collections/PriorityQueue.cs @@ -3,391 +3,224 @@ using System.Collections.Generic; using System.Collections; namespace Nuclex.Support.Collections { - /* - public class PriorityQueue : ICollection { - private struct HeapEntry { + /// Queue that dequeues items in order of their priority + public class PriorityQueue : ICollection, IEnumerable { - public HeapEntry(object item, int priority) { - this.item = item; - this.priority = priority; - } - public object Item { - get { return item; } - } - public int Priority { - get { return priority; } + #region class Enumerator + + /// Enumerates all items contained in a priority queue + private class Enumerator : IEnumerator { + + /// Initializes a new priority queue enumerator + /// Priority queue to be enumerated + public Enumerator(PriorityQueue priorityQueue) { + this.priorityQueue = priorityQueue; + Reset(); } - private object item; - private int priority; + /// Resets the enumerator to its initial state + public void Reset() { + index = -1; + version = priorityQueue.version; + } + + /// The current item being enumerated + ItemType IEnumerator.Current { + get { + checkVersion(); + return priorityQueue.heap[index]; + } + } + + /// Moves to the next item in the priority queue + /// True if a next item was found, false if the end has been reached + public bool MoveNext() { + checkVersion(); + + if(index + 1 == priorityQueue.count) + return false; + + ++index; + + return true; + } + + /// Releases all resources used by the enumerator + public void Dispose() { } + + /// Ensures that the priority queue has not changed + private void checkVersion() { + if(version != priorityQueue.version) + throw new InvalidOperationException("Priority queue has been modified"); + } + + /// The current item being enumerated + object IEnumerator.Current { + get { + checkVersion(); + return priorityQueue.heap[index]; + } + } + + /// Index of the current item in the priority queue + private int index; + /// The priority queue whose items this instance enumerates + private PriorityQueue priorityQueue; + /// Expected version of the priority queue + private int version; } - private int count; - private int capacity; - private int version; - private HeapEntry[] heap; + #endregion // class Enumerator - public PriorityQueue() { + /// Initializes a new priority queue + /// Comparer to use for ordering the items + public PriorityQueue(IComparer comparer) { + this.comparer = comparer; capacity = 15; // 15 is equal to 4 complete levels - heap = new HeapEntry[capacity]; + heap = new ItemType[capacity]; } - public object Dequeue() { + /// Takes the item with the highest priority off from the queue + /// The item with the highest priority in the list + public ItemType Dequeue() { if(count == 0) - throw new InvalidOperationException(); + throw new InvalidOperationException("No items available to dequeue"); - object result = heap[0].Item; - count--; + ItemType result = heap[0]; + --count; trickleDown(0, heap[count]); - version++; + + ++version; + return result; } - public void Enqueue(object item, int priority) { + /// Puts an item into the priority queue + /// Item to be queued + public void Enqueue(ItemType item) { if(count == capacity) growHeap(); - count++; - bubbleUp(count - 1, new HeapEntry(item, priority)); - version++; + + ++count; + bubbleUp(count - 1, item); + ++version; } - private void bubbleUp(int index, HeapEntry he) { - int parent = getParent(index); - // note: (index > 0) means there is a parent - while((index > 0) && (heap[parent].Priority < he.Priority)) { - heap[index] = heap[parent]; - index = parent; - parent = getParent(index); - } - heap[index] = he; + /// Removes all items from the priority queue + public void Clear() { + this.count = 0; + ++version; } - private int getLeftChild(int index) { - return (index * 2) + 1; - } - private int getParent(int index) { - return (index - 1) / 2; - } - - private void growHeap() { - capacity = (capacity * 2) + 1; - HeapEntry[] newHeap = new HeapEntry[capacity]; - System.Array.Copy(heap, 0, newHeap, 0, count); - heap = newHeap; - } - - private void trickleDown(int index, HeapEntry he) { - int child = getLeftChild(index); - while(child < count) { - if(((child + 1) < count) && - (heap[child].Priority < heap[child + 1].Priority)) { - child++; - } - heap[index] = heap[child]; - index = child; - child = getLeftChild(index); - } - bubbleUp(index, he); - } - - #region IEnumerable implementation - public IEnumerator GetEnumerator() { - return new PriorityQueueEnumerator(this); - } - #endregion - - #region ICollection implementation + /// Total number of items in the priority queue public int Count { - get { return count; } + get { return this.count; } } + /// Copies the contents of the priority queue into an array + /// Array to copy the priority queue into + /// Starting index for the destination array public void CopyTo(Array array, int index) { - System.Array.Copy(heap, 0, array, index, count); + Array.Copy(heap, 0, array, index, count); } + /// + /// Obtains an object that can be used to synchronize accesses to the priority queue + /// from different threads + /// public object SyncRoot { get { return this; } } + /// Whether operations performed on this priority queue are thread safe public bool IsSynchronized { get { return false; } } - #endregion - #region Priority Queue enumerator - private class PriorityQueueEnumerator : IEnumerator { - private int index; - private PriorityQueue pq; - private int version; - - public PriorityQueueEnumerator(PriorityQueue pq) { - this.pq = pq; - Reset(); - } - - private void checkVersion() { - if(version != pq.version) - throw new InvalidOperationException(); - } - - #region IEnumerator Members - - public void Reset() { - index = -1; - version = pq.version; - } - - public object Current { - get { - checkVersion(); - return pq.heap[index].Item; - } - } - - public bool MoveNext() { - checkVersion(); - if(index + 1 == pq.count) - return false; - index++; - return true; - } - - #endregion + /// Returns a typesafe enumerator for the priority queue + /// A new enumerator for the priority queue + public IEnumerator GetEnumerator() { + return new Enumerator(this); } - #endregion + + /// Moves an item upwards in the heap tree + /// Index of the item to be moved + /// Item to be moved + private void bubbleUp(int index, ItemType item) { + int parent = getParent(index); + + // note: (index > 0) means there is a parent + while((index > 0) && (this.comparer.Compare(heap[parent], item) < 0)) { + heap[index] = heap[parent]; + index = parent; + parent = getParent(index); + } + + heap[index] = item; + } + + /// Moved the item downwards in the heap tree + /// Index of the item to be moved + /// Item to be moved + private void trickleDown(int index, ItemType item) { + int child = getLeftChild(index); + + while(child < count) { + + if(((child + 1) < count) && (this.comparer.Compare(heap[child], heap[child + 1]) < 0)) + ++child; + + heap[index] = heap[child]; + index = child; + child = getLeftChild(index); + } + + bubbleUp(index, item); + } + + /// Obtains the left child item in the heap tree + /// Index of the item whose left child to return + /// The left child item of the provided parent item + private int getLeftChild(int index) { + return (index * 2) + 1; + } + + /// Calculates the parent entry of the item on the heap + /// Index of the item whose parent to calculate + /// The index of the parent to the specified item + private int getParent(int index) { + return (index - 1) / 2; + } + + /// Increases the size of the priority collection's heap + private void growHeap() { + capacity = (capacity * 2) + 1; + + ItemType[] newHeap = new ItemType[capacity]; + Array.Copy(heap, 0, newHeap, 0, count); + heap = newHeap; + } + + /// Returns an enumerator for the priority queue + /// A new enumerator for the priority queue + IEnumerator IEnumerable.GetEnumerator() { + return new Enumerator(this); + } + + /// Comparer used to order the items in the priority queue + private IComparer comparer; + /// Total number of items in the priority queue + private int count; + /// Available space in the priority queue + private int capacity; + /// Incremented whenever the priority queue is modified + private int version; + /// Tree containing the items in the priority queue + private ItemType[] heap; } - */ - /* - /// Queue that dequeues items in order of their priority - public class PriorityQueue : ICollection, IEnumerable { - public static PriorityQueue Syncronized(PriorityQueue P) { - return new PriorityQueue(ArrayList.Synchronized(P.InnerList), P.Comparer, false); - } - public static PriorityQueue ReadOnly(PriorityQueue P) { - return new PriorityQueue(ArrayList.ReadOnly(P.InnerList), P.Comparer, false); - } - - public PriorityQueue() - : this(Comparer.Default) { } - - public PriorityQueue(int C) - : this(Comparer.Default, C) { } - - public PriorityQueue(IComparer c) { - Comparer = c; - } - - public PriorityQueue(IComparer c, int Capacity) { - Comparer = c; - InnerList.Capacity = Capacity; - } - - protected PriorityQueue(ArrayList Core, IComparer Comp, bool Copy) { - if(Copy) - InnerList = Core.Clone() as ArrayList; - else - InnerList = Core; - Comparer = Comp; - } - - protected void SwitchElements(int i, int j) { - object h = InnerList[i]; - InnerList[i] = InnerList[j]; - InnerList[j] = h; - } - - protected virtual int OnCompare(int i, int j) { - return Comparer.Compare(InnerList[i], InnerList[j]); - } - - #region public methods - /// - /// Push an object onto the PQ - /// - /// The new object - /// - /// The index in the list where the object is _now_. This will change when - /// objects are taken from or put onto the PQ. - /// - public int Queue(object O) { - int p = InnerList.Count, p2; - InnerList.Add(O); // E[p] = O - do { - if(p == 0) - break; - p2 = (p - 1) / 2; - if(OnCompare(p, p2) < 0) { - SwitchElements(p, p2); - p = p2; - } else - break; - } while(true); - return p; - } - - /// - /// Get the smallest object and remove it. - /// - /// The smallest object - public object Dequeue() { - object result = InnerList[0]; - int p = 0, p1, p2, pn; - InnerList[0] = InnerList[InnerList.Count - 1]; - InnerList.RemoveAt(InnerList.Count - 1); - do { - pn = p; - p1 = 2 * p + 1; - p2 = 2 * p + 2; - if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner - p = p1; - if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner - p = p2; - - if(p == pn) - break; - SwitchElements(p, pn); - } while(true); - return result; - } - - /// - /// Notify the PQ that the object at position i has changed - /// and the PQ needs to restore order. - /// Since you dont have access to any indexes (except by using the - /// explicit IList.this) you should not call this function without knowing exactly - /// what you do. - /// - /// The index of the changed object. - public void Update(int i) { - int p = i, pn; - int p1, p2; - do // aufsteigen - { - if(p == 0) - break; - p2 = (p - 1) / 2; - if(OnCompare(p, p2) < 0) { - SwitchElements(p, p2); - p = p2; - } else - break; - } while(true); - if(p < i) - return; - do // absteigen - { - pn = p; - p1 = 2 * p + 1; - p2 = 2 * p + 2; - if(InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner - p = p1; - if(InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner - p = p2; - - if(p == pn) - break; - SwitchElements(p, pn); - } while(true); - } - - /// - /// Get the smallest object without removing it. - /// - /// The smallest object - public object Peek() { - if(InnerList.Count > 0) - return InnerList[0]; - return null; - } - - public bool Contains(object value) { - return InnerList.Contains(value); - } - - public void Clear() { - InnerList.Clear(); - } - - public int Count { - get { - return InnerList.Count; - } - } - IEnumerator IEnumerable.GetEnumerator() { - return InnerList.GetEnumerator(); - } - - public void CopyTo(Array array, int index) { - InnerList.CopyTo(array, index); - } - - public object Clone() { - return new PriorityQueue(InnerList, Comparer, true); - } - - public bool IsSynchronized { - get { - return InnerList.IsSynchronized; - } - } - - public object SyncRoot { - get { - return this; - } - } - #endregion - #region explicit implementation - bool IList.IsReadOnly { - get { - return false; - } - } - - object IList.this[int index] { - get { - return InnerList[index]; - } - set { - InnerList[index] = value; - Update(index); - } - } - - int IList.Add(object o) { - return Queue(o); - } - - void IList.RemoveAt(int index) { - throw new NotSupportedException(); - } - - void IList.Insert(int index, object value) { - throw new NotSupportedException(); - } - - void IList.Remove(object value) { - throw new NotSupportedException(); - } - - int IList.IndexOf(object value) { - throw new NotSupportedException(); - } - - bool IList.IsFixedSize { - get { - return false; - } - } - #endregion - - protected ArrayList InnerList = new ArrayList(); - protected IComparer Comparer; - } - */ } // namespace Nuclex.Support.Collections diff --git a/Source/Collections/UnintrusivePriorityQueue.Test.cs b/Source/Collections/UnintrusivePriorityQueue.Test.cs new file mode 100644 index 0000000..0d2b732 --- /dev/null +++ b/Source/Collections/UnintrusivePriorityQueue.Test.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; + +#if UNITTEST + +using NUnit.Framework; + +namespace Nuclex.Support.Collections { + + /// Unit Test for the priority queue class + [TestFixture] + public class UnintrusivePriorityQueueTest { + + /// Tests to ensure the count property is properly updated + [Test] + public void TestCount() { + UnintrusivePriorityQueue testQueue = + new UnintrusivePriorityQueue(); + + Assert.AreEqual(0, testQueue.Count); + testQueue.Enqueue("a", 12.34f); + Assert.AreEqual(1, testQueue.Count); + testQueue.Enqueue("b", 56.78f); + Assert.AreEqual(2, testQueue.Count); + testQueue.Dequeue(); + Assert.AreEqual(1, testQueue.Count); + testQueue.Enqueue("c", 9.0f); + Assert.AreEqual(2, testQueue.Count); + testQueue.Clear(); + Assert.AreEqual(0, testQueue.Count); + } + + /// Tests to ensure that the priority collection actually sorts items + [Test] + public void TestOrdering() { + UnintrusivePriorityQueue testQueue = + new UnintrusivePriorityQueue(); + + testQueue.Enqueue("a", 1.0f); + testQueue.Enqueue("i", 9.0f); + testQueue.Enqueue("b", 2.0f); + testQueue.Enqueue("h", 8.0f); + testQueue.Enqueue("c", 3.0f); + testQueue.Enqueue("g", 7.0f); + testQueue.Enqueue("d", 4.0f); + testQueue.Enqueue("f", 6.0f); + testQueue.Enqueue("e", 5.0f); + + Assert.AreEqual("i", testQueue.Dequeue()); + Assert.AreEqual("h", testQueue.Dequeue()); + Assert.AreEqual("g", testQueue.Dequeue()); + Assert.AreEqual("f", testQueue.Dequeue()); + Assert.AreEqual("e", testQueue.Dequeue()); + Assert.AreEqual("d", testQueue.Dequeue()); + Assert.AreEqual("c", testQueue.Dequeue()); + Assert.AreEqual("b", testQueue.Dequeue()); + Assert.AreEqual("a", testQueue.Dequeue()); + } + + } + +} // namespace Nuclex.Support.Collections + +#endif // UNITTEST diff --git a/Source/Collections/UnintrusivePriorityQueue.cs b/Source/Collections/UnintrusivePriorityQueue.cs new file mode 100644 index 0000000..e17ba0f --- /dev/null +++ b/Source/Collections/UnintrusivePriorityQueue.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Collections; + +namespace Nuclex.Support.Collections { + + /// Queue that dequeues items in order of their priority + public class UnintrusivePriorityQueue + : ICollection, IEnumerable where PriorityType : IComparable { + + #region struct Entry + + /// An entry in the priority queue + private struct Entry { + + /// Initializes a new priority queue entry + /// Item to be stored in the entry + /// Priority of the item in the entry + public Entry(ItemType item, PriorityType priority) { + this.Item = item; + this.Priority = priority; + } + + /// Item contained in this priority queue entry + public ItemType Item; + /// Priority assigned to this entry + public PriorityType Priority; + + } + + #endregion // struct Entry + + #region class EntryComparer + + /// Compares two priority queue entries based on their priority + private class EntryComparer : IComparer { + + /// Compares the left entry to the right entry + /// Entry on the left side + /// Entry on the right side + /// The relationship of the two entries + public int Compare(Entry left, Entry right) { + return left.Priority.CompareTo(right.Priority); + } + + /// Default instance for this comparer + public static readonly EntryComparer Instance = new EntryComparer(); + + } + + #endregion // class EntryComparer + + #region class UnwrappingEnumerator + + /// Enumerates all items contained in a priority queue + private class UnwrappingEnumerator : IEnumerator { + + /// Initializes a new priority queue enumerator + /// Enumerator of entries to unwrap + public UnwrappingEnumerator(IEnumerator entryEnumerator) { + this.entryEnumerator = entryEnumerator; + } + + /// Resets the enumerator to its initial state + public void Reset() { + this.entryEnumerator.Reset(); + } + + /// The current item being enumerated + ItemType IEnumerator.Current { + get { return this.entryEnumerator.Current.Item; } + } + + /// Releases all resources used by the enumerator + public void Dispose() { + this.entryEnumerator.Dispose(); + } + + /// Moves to the next item in the priority queue + /// True if a next item was found, false if the end has been reached + public bool MoveNext() { + return this.entryEnumerator.MoveNext(); + } + + /// The current item being enumerated + object IEnumerator.Current { + get { return this.entryEnumerator.Current.Item; } + } + + /// Enumerator for entries to be unwrapped by this enumerator + private IEnumerator entryEnumerator; + + } + + #endregion // class Enumerator + + /// Initializes a new non-intrusive priority queue + public UnintrusivePriorityQueue() { + this.intrusiveQueue = new PriorityQueue(EntryComparer.Instance); + } + + /// Takes the item with the highest priority off from the queue + /// The item with the highest priority in the list + public ItemType Dequeue() { + return this.intrusiveQueue.Dequeue().Item; + } + + /// Puts an item into the priority queue + /// Item to be queued + /// Priority of the item to be queued + public void Enqueue(ItemType item, PriorityType priority) { + this.intrusiveQueue.Enqueue(new Entry(item, priority)); + } + + /// Removes all items from the priority queue + public void Clear() { + this.intrusiveQueue.Clear(); + } + + /// Total number of items in the priority queue + public int Count { + get { return this.intrusiveQueue.Count; } + } + + /// Copies the contents of the priority queue into an array + /// Array to copy the priority queue into + /// Starting index for the destination array + public void CopyTo(Array array, int index) { + + Entry[] entries = new Entry[this.intrusiveQueue.Count]; + + this.intrusiveQueue.CopyTo(array, 0); + + for(int entryIndex = 0; entryIndex < this.intrusiveQueue.Count; ++entryIndex) + array.SetValue(entries[entryIndex], entryIndex + index); + + } + + /// + /// Obtains an object that can be used to synchronize accesses to the priority queue + /// from different threads + /// + public object SyncRoot { + get { return this.intrusiveQueue.SyncRoot; } + } + + /// Whether operations performed on this priority queue are thread safe + public bool IsSynchronized { + get { return this.intrusiveQueue.IsSynchronized; } + } + + /// Returns a typesafe enumerator for the priority queue + /// A new enumerator for the priority queue + public IEnumerator GetEnumerator() { + return new UnwrappingEnumerator(this.intrusiveQueue.GetEnumerator()); + } + + /// Returns an enumerator for the priority queue + /// A new enumerator for the priority queue + IEnumerator IEnumerable.GetEnumerator() { + return new UnwrappingEnumerator(this.intrusiveQueue.GetEnumerator()); + } + + /// Intrusive priority queue being wrapped by this class + private PriorityQueue intrusiveQueue; + + } + +} // namespace Nuclex.Support.Collections