diff options
Diffstat (limited to 'ThirdParty/SmartThreadPool/PriorityQueue.cs')
-rw-r--r-- | ThirdParty/SmartThreadPool/PriorityQueue.cs | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/ThirdParty/SmartThreadPool/PriorityQueue.cs b/ThirdParty/SmartThreadPool/PriorityQueue.cs new file mode 100644 index 0000000..63d5e84 --- /dev/null +++ b/ThirdParty/SmartThreadPool/PriorityQueue.cs | |||
@@ -0,0 +1,240 @@ | |||
1 | // Ami Bar | ||
2 | // amibar@gmail.com | ||
3 | |||
4 | using System; | ||
5 | using System.Collections; | ||
6 | using System.Diagnostics; | ||
7 | |||
8 | namespace Amib.Threading.Internal | ||
9 | { | ||
10 | #region PriorityQueue class | ||
11 | |||
12 | /// <summary> | ||
13 | /// PriorityQueue class | ||
14 | /// This class is not thread safe because we use external lock | ||
15 | /// </summary> | ||
16 | public sealed class PriorityQueue : IEnumerable | ||
17 | { | ||
18 | #region Private members | ||
19 | |||
20 | /// <summary> | ||
21 | /// The number of queues, there is one for each type of priority | ||
22 | /// </summary> | ||
23 | private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1; | ||
24 | |||
25 | /// <summary> | ||
26 | /// Work items queues. There is one for each type of priority | ||
27 | /// </summary> | ||
28 | private Queue [] _queues = new Queue[_queuesCount]; | ||
29 | |||
30 | /// <summary> | ||
31 | /// The total number of work items within the queues | ||
32 | /// </summary> | ||
33 | private int _workItemsCount = 0; | ||
34 | |||
35 | /// <summary> | ||
36 | /// Use with IEnumerable interface | ||
37 | /// </summary> | ||
38 | private int _version = 0; | ||
39 | |||
40 | #endregion | ||
41 | |||
42 | #region Contructor | ||
43 | |||
44 | public PriorityQueue() | ||
45 | { | ||
46 | for(int i = 0; i < _queues.Length; ++i) | ||
47 | { | ||
48 | _queues[i] = new Queue(); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | #endregion | ||
53 | |||
54 | #region Methods | ||
55 | |||
56 | /// <summary> | ||
57 | /// Enqueue a work item. | ||
58 | /// </summary> | ||
59 | /// <param name="workItem">A work item</param> | ||
60 | public void Enqueue(IHasWorkItemPriority workItem) | ||
61 | { | ||
62 | Debug.Assert(null != workItem); | ||
63 | |||
64 | int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1; | ||
65 | Debug.Assert(queueIndex >= 0); | ||
66 | Debug.Assert(queueIndex < _queuesCount); | ||
67 | |||
68 | _queues[queueIndex].Enqueue(workItem); | ||
69 | ++_workItemsCount; | ||
70 | ++_version; | ||
71 | } | ||
72 | |||
73 | /// <summary> | ||
74 | /// Dequeque a work item. | ||
75 | /// </summary> | ||
76 | /// <returns>Returns the next work item</returns> | ||
77 | public IHasWorkItemPriority Dequeue() | ||
78 | { | ||
79 | IHasWorkItemPriority workItem = null; | ||
80 | |||
81 | if(_workItemsCount > 0) | ||
82 | { | ||
83 | int queueIndex = GetNextNonEmptyQueue(-1); | ||
84 | Debug.Assert(queueIndex >= 0); | ||
85 | workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority; | ||
86 | Debug.Assert(null != workItem); | ||
87 | --_workItemsCount; | ||
88 | ++_version; | ||
89 | } | ||
90 | |||
91 | return workItem; | ||
92 | } | ||
93 | |||
94 | /// <summary> | ||
95 | /// Find the next non empty queue starting at queue queueIndex+1 | ||
96 | /// </summary> | ||
97 | /// <param name="queueIndex">The index-1 to start from</param> | ||
98 | /// <returns> | ||
99 | /// The index of the next non empty queue or -1 if all the queues are empty | ||
100 | /// </returns> | ||
101 | private int GetNextNonEmptyQueue(int queueIndex) | ||
102 | { | ||
103 | for(int i = queueIndex+1; i < _queuesCount; ++i) | ||
104 | { | ||
105 | if(_queues[i].Count > 0) | ||
106 | { | ||
107 | return i; | ||
108 | } | ||
109 | } | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | /// <summary> | ||
114 | /// The number of work items | ||
115 | /// </summary> | ||
116 | public int Count | ||
117 | { | ||
118 | get | ||
119 | { | ||
120 | return _workItemsCount; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /// <summary> | ||
125 | /// Clear all the work items | ||
126 | /// </summary> | ||
127 | public void Clear() | ||
128 | { | ||
129 | if (_workItemsCount > 0) | ||
130 | { | ||
131 | foreach(Queue queue in _queues) | ||
132 | { | ||
133 | queue.Clear(); | ||
134 | } | ||
135 | _workItemsCount = 0; | ||
136 | ++_version; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | #endregion | ||
141 | |||
142 | #region IEnumerable Members | ||
143 | |||
144 | /// <summary> | ||
145 | /// Returns an enumerator to iterate over the work items | ||
146 | /// </summary> | ||
147 | /// <returns>Returns an enumerator</returns> | ||
148 | public IEnumerator GetEnumerator() | ||
149 | { | ||
150 | return new PriorityQueueEnumerator(this); | ||
151 | } | ||
152 | |||
153 | #endregion | ||
154 | |||
155 | #region PriorityQueueEnumerator | ||
156 | |||
157 | /// <summary> | ||
158 | /// The class the implements the enumerator | ||
159 | /// </summary> | ||
160 | private class PriorityQueueEnumerator : IEnumerator | ||
161 | { | ||
162 | private PriorityQueue _priorityQueue; | ||
163 | private int _version; | ||
164 | private int _queueIndex; | ||
165 | private IEnumerator _enumerator; | ||
166 | |||
167 | public PriorityQueueEnumerator(PriorityQueue priorityQueue) | ||
168 | { | ||
169 | _priorityQueue = priorityQueue; | ||
170 | _version = _priorityQueue._version; | ||
171 | _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); | ||
172 | if (_queueIndex >= 0) | ||
173 | { | ||
174 | _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); | ||
175 | } | ||
176 | else | ||
177 | { | ||
178 | _enumerator = null; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | #region IEnumerator Members | ||
183 | |||
184 | public void Reset() | ||
185 | { | ||
186 | _version = _priorityQueue._version; | ||
187 | _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); | ||
188 | if (_queueIndex >= 0) | ||
189 | { | ||
190 | _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | _enumerator = null; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | public object Current | ||
199 | { | ||
200 | get | ||
201 | { | ||
202 | Debug.Assert(null != _enumerator); | ||
203 | return _enumerator.Current; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | public bool MoveNext() | ||
208 | { | ||
209 | if (null == _enumerator) | ||
210 | { | ||
211 | return false; | ||
212 | } | ||
213 | |||
214 | if(_version != _priorityQueue._version) | ||
215 | { | ||
216 | throw new InvalidOperationException("The collection has been modified"); | ||
217 | |||
218 | } | ||
219 | if (!_enumerator.MoveNext()) | ||
220 | { | ||
221 | _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex); | ||
222 | if(-1 == _queueIndex) | ||
223 | { | ||
224 | return false; | ||
225 | } | ||
226 | _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); | ||
227 | _enumerator.MoveNext(); | ||
228 | return true; | ||
229 | } | ||
230 | return true; | ||
231 | } | ||
232 | |||
233 | #endregion | ||
234 | } | ||
235 | |||
236 | #endregion | ||
237 | } | ||
238 | |||
239 | #endregion | ||
240 | } | ||