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