123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- namespace Amib.Threading.Internal
- {
- #region PriorityQueue class
- /// <summary>
- /// PriorityQueue class
- /// This class is not thread safe because we use external lock
- /// </summary>
- public sealed class PriorityQueue : IEnumerable
- {
- #region Private members
- /// <summary>
- /// The number of queues, there is one for each type of priority
- /// </summary>
- private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
- /// <summary>
- /// Work items queues. There is one for each type of priority
- /// </summary>
- private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount];
- /// <summary>
- /// The total number of work items within the queues
- /// </summary>
- private int _workItemsCount;
- /// <summary>
- /// Use with IEnumerable interface
- /// </summary>
- private int _version;
- #endregion
- #region Contructor
- public PriorityQueue()
- {
- for(int i = 0; i < _queues.Length; ++i)
- {
- _queues[i] = new LinkedList<IHasWorkItemPriority>();
- }
- }
- #endregion
- #region Methods
- /// <summary>
- /// Enqueue a work item.
- /// </summary>
- /// <param name="workItem">A work item</param>
- public void Enqueue(IHasWorkItemPriority workItem)
- {
- Debug.Assert(null != workItem);
- int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
- Debug.Assert(queueIndex >= 0);
- Debug.Assert(queueIndex < _queuesCount);
- _queues[queueIndex].AddLast(workItem);
- ++_workItemsCount;
- ++_version;
- }
- /// <summary>
- /// Dequeque a work item.
- /// </summary>
- /// <returns>Returns the next work item</returns>
- public IHasWorkItemPriority Dequeue()
- {
- IHasWorkItemPriority workItem = null;
- if(_workItemsCount > 0)
- {
- int queueIndex = GetNextNonEmptyQueue(-1);
- Debug.Assert(queueIndex >= 0);
- workItem = _queues[queueIndex].First.Value;
- _queues[queueIndex].RemoveFirst();
- Debug.Assert(null != workItem);
- --_workItemsCount;
- ++_version;
- }
- return workItem;
- }
- /// <summary>
- /// Find the next non empty queue starting at queue queueIndex+1
- /// </summary>
- /// <param name="queueIndex">The index-1 to start from</param>
- /// <returns>
- /// The index of the next non empty queue or -1 if all the queues are empty
- /// </returns>
- private int GetNextNonEmptyQueue(int queueIndex)
- {
- for(int i = queueIndex+1; i < _queuesCount; ++i)
- {
- if(_queues[i].Count > 0)
- {
- return i;
- }
- }
- return -1;
- }
- /// <summary>
- /// The number of work items
- /// </summary>
- public int Count
- {
- get
- {
- return _workItemsCount;
- }
- }
- /// <summary>
- /// Clear all the work items
- /// </summary>
- public void Clear()
- {
- if (_workItemsCount > 0)
- {
- foreach(LinkedList<IHasWorkItemPriority> queue in _queues)
- {
- queue.Clear();
- }
- _workItemsCount = 0;
- ++_version;
- }
- }
- #endregion
- #region IEnumerable Members
- /// <summary>
- /// Returns an enumerator to iterate over the work items
- /// </summary>
- /// <returns>Returns an enumerator</returns>
- public IEnumerator GetEnumerator()
- {
- return new PriorityQueueEnumerator(this);
- }
- #endregion
- #region PriorityQueueEnumerator
- /// <summary>
- /// The class the implements the enumerator
- /// </summary>
- private class PriorityQueueEnumerator : IEnumerator
- {
- private readonly PriorityQueue _priorityQueue;
- private int _version;
- private int _queueIndex;
- private IEnumerator _enumerator;
- public PriorityQueueEnumerator(PriorityQueue priorityQueue)
- {
- _priorityQueue = priorityQueue;
- _version = _priorityQueue._version;
- _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
- if (_queueIndex >= 0)
- {
- _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
- }
- else
- {
- _enumerator = null;
- }
- }
- #region IEnumerator Members
- public void Reset()
- {
- _version = _priorityQueue._version;
- _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
- if (_queueIndex >= 0)
- {
- _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
- }
- else
- {
- _enumerator = null;
- }
- }
- public object Current
- {
- get
- {
- Debug.Assert(null != _enumerator);
- return _enumerator.Current;
- }
- }
- public bool MoveNext()
- {
- if (null == _enumerator)
- {
- return false;
- }
- if(_version != _priorityQueue._version)
- {
- throw new InvalidOperationException("The collection has been modified");
- }
- if (!_enumerator.MoveNext())
- {
- _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
- if(-1 == _queueIndex)
- {
- return false;
- }
- _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
- _enumerator.MoveNext();
- return true;
- }
- return true;
- }
- #endregion
- }
- #endregion
- }
- #endregion
- }
|