#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2007 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
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