diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/MinHeap.cs | 150 |
1 files changed, 80 insertions, 70 deletions
diff --git a/OpenSim/Framework/MinHeap.cs b/OpenSim/Framework/MinHeap.cs index 99ac25d..68f6668 100644 --- a/OpenSim/Framework/MinHeap.cs +++ b/OpenSim/Framework/MinHeap.cs | |||
@@ -45,8 +45,8 @@ namespace OpenSim.Framework | |||
45 | 45 | ||
46 | internal void Clear() | 46 | internal void Clear() |
47 | { | 47 | { |
48 | this.index = -1; | 48 | index = -1; |
49 | this.heap = null; | 49 | heap = null; |
50 | } | 50 | } |
51 | } | 51 | } |
52 | 52 | ||
@@ -55,23 +55,26 @@ namespace OpenSim.Framework | |||
55 | internal T value; | 55 | internal T value; |
56 | internal Handle handle; | 56 | internal Handle handle; |
57 | 57 | ||
58 | internal HeapItem(T value, Handle handle) | 58 | internal HeapItem(T _value, Handle _handle) |
59 | { | 59 | { |
60 | this.value = value; | 60 | value = _value; |
61 | this.handle = handle; | 61 | handle = _handle; |
62 | } | 62 | } |
63 | 63 | ||
64 | internal void Clear() | 64 | internal void Clear() |
65 | { | 65 | { |
66 | if (this.handle != null) | 66 | if (handle != null) |
67 | this.handle.Clear(); | 67 | { |
68 | ClearRef(); | 68 | handle.Clear(); |
69 | handle = null; | ||
70 | } | ||
71 | value = default(T); | ||
69 | } | 72 | } |
70 | 73 | ||
71 | internal void ClearRef() | 74 | internal void ClearRef() |
72 | { | 75 | { |
73 | this.value = default(T); | 76 | value = default(T); |
74 | this.handle = null; | 77 | handle = null; |
75 | } | 78 | } |
76 | } | 79 | } |
77 | 80 | ||
@@ -81,6 +84,7 @@ namespace OpenSim.Framework | |||
81 | private int size; | 84 | private int size; |
82 | private object sync_root; | 85 | private object sync_root; |
83 | private int version; | 86 | private int version; |
87 | private int capacity; | ||
84 | 88 | ||
85 | private Comparison<T> comparison; | 89 | private Comparison<T> comparison; |
86 | 90 | ||
@@ -90,14 +94,15 @@ namespace OpenSim.Framework | |||
90 | public MinHeap(int capacity, IComparer<T> comparer) : | 94 | public MinHeap(int capacity, IComparer<T> comparer) : |
91 | this(capacity, new Comparison<T>(comparer.Compare)) { } | 95 | this(capacity, new Comparison<T>(comparer.Compare)) { } |
92 | public MinHeap(Comparison<T> comparison) : this(DEFAULT_CAPACITY, comparison) { } | 96 | public MinHeap(Comparison<T> comparison) : this(DEFAULT_CAPACITY, comparison) { } |
93 | public MinHeap(int capacity, Comparison<T> comparison) | 97 | public MinHeap(int _capacity, Comparison<T> _comparison) |
94 | { | 98 | { |
95 | this.items = new HeapItem[capacity]; | 99 | capacity = _capacity; |
96 | this.comparison = comparison; | 100 | items = new HeapItem[capacity]; |
97 | this.size = this.version = 0; | 101 | comparison = _comparison; |
102 | size = version = 0; | ||
98 | } | 103 | } |
99 | 104 | ||
100 | public int Count { get { return this.size; } } | 105 | public int Count { get { return size; } } |
101 | 106 | ||
102 | public bool IsReadOnly { get { return false; } } | 107 | public bool IsReadOnly { get { return false; } } |
103 | 108 | ||
@@ -108,15 +113,16 @@ namespace OpenSim.Framework | |||
108 | get | 113 | get |
109 | { | 114 | { |
110 | Handle handle = ValidateThisHandle(key); | 115 | Handle handle = ValidateThisHandle(key); |
111 | return this.items[handle.index].value; | 116 | return items[handle.index].value; |
112 | } | 117 | } |
113 | 118 | ||
114 | set | 119 | set |
115 | { | 120 | { |
116 | Handle handle = ValidateThisHandle(key); | 121 | Handle handle = ValidateThisHandle(key); |
117 | this.items[handle.index].value = value; | 122 | int indx = handle.index; |
118 | if (!BubbleUp(handle.index)) | 123 | items[indx].value = value; |
119 | BubbleDown(handle.index); | 124 | if (!BubbleUp(indx)) |
125 | BubbleDown(indx); | ||
120 | } | 126 | } |
121 | } | 127 | } |
122 | 128 | ||
@@ -124,9 +130,9 @@ namespace OpenSim.Framework | |||
124 | { | 130 | { |
125 | get | 131 | get |
126 | { | 132 | { |
127 | if (this.sync_root == null) | 133 | if (sync_root == null) |
128 | Interlocked.CompareExchange<object>(ref this.sync_root, new object(), null); | 134 | Interlocked.CompareExchange<object>(ref sync_root, new object(), null); |
129 | return this.sync_root; | 135 | return sync_root; |
130 | } | 136 | } |
131 | } | 137 | } |
132 | 138 | ||
@@ -152,27 +158,27 @@ namespace OpenSim.Framework | |||
152 | 158 | ||
153 | private void Set(HeapItem item, int index) | 159 | private void Set(HeapItem item, int index) |
154 | { | 160 | { |
155 | this.items[index] = item; | 161 | items[index] = item; |
156 | if (item.handle != null) | 162 | if (item.handle != null) |
157 | item.handle.index = index; | 163 | item.handle.index = index; |
158 | } | 164 | } |
159 | 165 | ||
160 | private bool BubbleUp(int index) | 166 | private bool BubbleUp(int index) |
161 | { | 167 | { |
162 | HeapItem item = this.items[index]; | 168 | HeapItem item = items[index]; |
163 | int current, parent; | 169 | int current, parent; |
164 | 170 | ||
165 | for (current = index, parent = (current - 1) / 2; | 171 | for (current = index, parent = (current - 1) / 2; |
166 | (current > 0) && (this.comparison(this.items[parent].value, item.value)) > 0; | 172 | (current > 0) && (comparison(items[parent].value, item.value)) > 0; |
167 | current = parent, parent = (current - 1) / 2) | 173 | current = parent, parent = (current - 1) / 2) |
168 | { | 174 | { |
169 | Set(this.items[parent], current); | 175 | Set(items[parent], current); |
170 | } | 176 | } |
171 | 177 | ||
172 | if (current != index) | 178 | if (current != index) |
173 | { | 179 | { |
174 | Set(item, current); | 180 | Set(item, current); |
175 | ++this.version; | 181 | ++version; |
176 | return true; | 182 | return true; |
177 | } | 183 | } |
178 | return false; | 184 | return false; |
@@ -180,24 +186,24 @@ namespace OpenSim.Framework | |||
180 | 186 | ||
181 | private void BubbleDown(int index) | 187 | private void BubbleDown(int index) |
182 | { | 188 | { |
183 | HeapItem item = this.items[index]; | 189 | HeapItem item = items[index]; |
184 | int current, child; | 190 | int current, child; |
185 | 191 | ||
186 | for (current = index, child = (2 * current) + 1; | 192 | for (current = index, child = (2 * current) + 1; |
187 | current < this.size / 2; | 193 | current < size / 2; |
188 | current = child, child = (2 * current) + 1) | 194 | current = child, child = (2 * current) + 1) |
189 | { | 195 | { |
190 | if ((child < this.size - 1) && this.comparison(this.items[child].value, this.items[child + 1].value) > 0) | 196 | if ((child < size - 1) && comparison(items[child].value, items[child + 1].value) > 0) |
191 | ++child; | 197 | ++child; |
192 | if (this.comparison(this.items[child].value, item.value) >= 0) | 198 | if (comparison(items[child].value, item.value) >= 0) |
193 | break; | 199 | break; |
194 | Set(this.items[child], current); | 200 | Set(items[child], current); |
195 | } | 201 | } |
196 | 202 | ||
197 | if (current != index) | 203 | if (current != index) |
198 | { | 204 | { |
199 | Set(item, current); | 205 | Set(item, current); |
200 | ++this.version; | 206 | ++version; |
201 | } | 207 | } |
202 | } | 208 | } |
203 | 209 | ||
@@ -206,7 +212,7 @@ namespace OpenSim.Framework | |||
206 | Handle handle = ValidateHandle(key); | 212 | Handle handle = ValidateHandle(key); |
207 | if (handle.index > -1) | 213 | if (handle.index > -1) |
208 | { | 214 | { |
209 | value = this.items[handle.index].value; | 215 | value = items[handle.index].value; |
210 | return true; | 216 | return true; |
211 | } | 217 | } |
212 | value = default(T); | 218 | value = default(T); |
@@ -228,12 +234,12 @@ namespace OpenSim.Framework | |||
228 | 234 | ||
229 | public void Add(T value, IHandle ihandle) | 235 | public void Add(T value, IHandle ihandle) |
230 | { | 236 | { |
231 | if (this.size == this.items.Length) | 237 | if (size == items.Length) |
232 | { | 238 | { |
233 | int capacity = (int)((this.items.Length * 200L) / 100L); | 239 | int capacity = (int)((items.Length * 200L) / 100L); |
234 | if (capacity < (this.items.Length + DEFAULT_CAPACITY)) | 240 | if (capacity < (items.Length + DEFAULT_CAPACITY)) |
235 | capacity = this.items.Length + DEFAULT_CAPACITY; | 241 | capacity = items.Length + DEFAULT_CAPACITY; |
236 | Array.Resize<HeapItem>(ref this.items, capacity); | 242 | Array.Resize<HeapItem>(ref items, capacity); |
237 | } | 243 | } |
238 | 244 | ||
239 | Handle handle = null; | 245 | Handle handle = null; |
@@ -245,8 +251,8 @@ namespace OpenSim.Framework | |||
245 | 251 | ||
246 | HeapItem item = new MinHeap<T>.HeapItem(value, handle); | 252 | HeapItem item = new MinHeap<T>.HeapItem(value, handle); |
247 | 253 | ||
248 | Set(item, this.size); | 254 | Set(item, size); |
249 | BubbleUp(this.size++); | 255 | BubbleUp(size++); |
250 | } | 256 | } |
251 | 257 | ||
252 | public void Add(T value) | 258 | public void Add(T value) |
@@ -256,50 +262,54 @@ namespace OpenSim.Framework | |||
256 | 262 | ||
257 | public T Min() | 263 | public T Min() |
258 | { | 264 | { |
259 | if (this.size == 0) | 265 | if (size == 0) |
260 | throw new InvalidOperationException("Heap is empty"); | 266 | throw new InvalidOperationException("Heap is empty"); |
261 | 267 | ||
262 | return this.items[0].value; | 268 | return items[0].value; |
263 | } | 269 | } |
264 | 270 | ||
265 | public void Clear() | 271 | public void Clear() |
266 | { | 272 | { |
267 | for (int index = 0; index < this.size; ++index) | 273 | for (int index = 0; index < size; ++index) |
268 | this.items[index].Clear(); | 274 | items[index].Clear(); |
269 | this.size = 0; | 275 | size = 0; |
270 | ++this.version; | 276 | if(items.Length > capacity) |
277 | items = new HeapItem[capacity]; | ||
278 | ++version; | ||
271 | } | 279 | } |
272 | 280 | ||
273 | public void TrimExcess() | 281 | public void TrimExcess() |
274 | { | 282 | { |
275 | int length = (int)(this.items.Length * 0.9); | 283 | int length = (int)(items.Length * 0.9); |
276 | if (this.size < length) | 284 | if (size < length) |
277 | Array.Resize<HeapItem>(ref this.items, Math.Min(this.size, DEFAULT_CAPACITY)); | 285 | Array.Resize<HeapItem>(ref items, Math.Min(size, capacity)); |
278 | } | 286 | } |
279 | 287 | ||
280 | private void RemoveAt(int index) | 288 | private void RemoveAt(int index) |
281 | { | 289 | { |
282 | if (this.size == 0) | 290 | if (size == 0) |
283 | throw new InvalidOperationException("Heap is empty"); | 291 | throw new InvalidOperationException("Heap is empty"); |
284 | if (index >= this.size) | 292 | if (index >= size) |
285 | throw new ArgumentOutOfRangeException("index"); | 293 | throw new ArgumentOutOfRangeException("index"); |
286 | 294 | ||
287 | this.items[index].Clear(); | 295 | items[index].Clear(); |
288 | if (--this.size > 0 && index != this.size) | 296 | if (--size > 0 && index != size) |
289 | { | 297 | { |
290 | Set(this.items[this.size], index); | 298 | Set(items[size], index); |
291 | this.items[this.size].ClearRef(); | 299 | items[size].ClearRef(); |
292 | if (!BubbleUp(index)) | 300 | if (!BubbleUp(index)) |
293 | BubbleDown(index); | 301 | BubbleDown(index); |
294 | } | 302 | } |
303 | if(size == 0 && items.Length > 4 * capacity) | ||
304 | items = new HeapItem[capacity]; | ||
295 | } | 305 | } |
296 | 306 | ||
297 | public T RemoveMin() | 307 | public T RemoveMin() |
298 | { | 308 | { |
299 | if (this.size == 0) | 309 | if (size == 0) |
300 | throw new InvalidOperationException("Heap is empty"); | 310 | throw new InvalidOperationException("Heap is empty"); |
301 | 311 | ||
302 | HeapItem item = this.items[0]; | 312 | HeapItem item = items[0]; |
303 | RemoveAt(0); | 313 | RemoveAt(0); |
304 | return item.value; | 314 | return item.value; |
305 | } | 315 | } |
@@ -307,7 +317,7 @@ namespace OpenSim.Framework | |||
307 | public T Remove(IHandle ihandle) | 317 | public T Remove(IHandle ihandle) |
308 | { | 318 | { |
309 | Handle handle = ValidateThisHandle(ihandle); | 319 | Handle handle = ValidateThisHandle(ihandle); |
310 | HeapItem item = this.items[handle.index]; | 320 | HeapItem item = items[handle.index]; |
311 | RemoveAt(handle.index); | 321 | RemoveAt(handle.index); |
312 | return item.value; | 322 | return item.value; |
313 | } | 323 | } |
@@ -317,9 +327,9 @@ namespace OpenSim.Framework | |||
317 | EqualityComparer<T> comparer = EqualityComparer<T>.Default; | 327 | EqualityComparer<T> comparer = EqualityComparer<T>.Default; |
318 | int index; | 328 | int index; |
319 | 329 | ||
320 | for (index = 0; index < this.size; ++index) | 330 | for (index = 0; index < size; ++index) |
321 | { | 331 | { |
322 | if (comparer.Equals(this.items[index].value, value)) | 332 | if (comparer.Equals(items[index].value, value)) |
323 | return index; | 333 | return index; |
324 | } | 334 | } |
325 | return -1; | 335 | return -1; |
@@ -356,8 +366,8 @@ namespace OpenSim.Framework | |||
356 | if ((length - index) < this.size) | 366 | if ((length - index) < this.size) |
357 | throw new ArgumentException("Not enough space available in array starting at index"); | 367 | throw new ArgumentException("Not enough space available in array starting at index"); |
358 | 368 | ||
359 | for (int i = 0; i < this.size; ++i) | 369 | for (int i = 0; i < size; ++i) |
360 | array[index + i] = this.items[i].value; | 370 | array[index + i] = items[i].value; |
361 | } | 371 | } |
362 | 372 | ||
363 | public void CopyTo(Array array, int index) | 373 | public void CopyTo(Array array, int index) |
@@ -372,13 +382,13 @@ namespace OpenSim.Framework | |||
372 | int length = array.Length; | 382 | int length = array.Length; |
373 | if ((index < 0) || (index > length)) | 383 | if ((index < 0) || (index > length)) |
374 | throw new ArgumentOutOfRangeException("index"); | 384 | throw new ArgumentOutOfRangeException("index"); |
375 | if ((length - index) < this.size) | 385 | if ((length - index) < size) |
376 | throw new ArgumentException("Not enough space available in array starting at index"); | 386 | throw new ArgumentException("Not enough space available in array starting at index"); |
377 | 387 | ||
378 | try | 388 | try |
379 | { | 389 | { |
380 | for (int i = 0; i < this.size; ++i) | 390 | for (int i = 0; i < size; ++i) |
381 | array.SetValue(this.items[i].value, index + i); | 391 | array.SetValue(items[i].value, index + i); |
382 | } | 392 | } |
383 | catch (ArrayTypeMismatchException) | 393 | catch (ArrayTypeMismatchException) |
384 | { | 394 | { |
@@ -388,13 +398,13 @@ namespace OpenSim.Framework | |||
388 | 398 | ||
389 | public IEnumerator<T> GetEnumerator() | 399 | public IEnumerator<T> GetEnumerator() |
390 | { | 400 | { |
391 | int version = this.version; | 401 | int cversion = version; |
392 | 402 | ||
393 | for (int index = 0; index < this.size; ++index) | 403 | for (int index = 0; index < size; ++index) |
394 | { | 404 | { |
395 | if (version != this.version) | 405 | if (cversion != version) |
396 | throw new InvalidOperationException("Heap was modified while enumerating"); | 406 | throw new InvalidOperationException("Heap was modified while enumerating"); |
397 | yield return this.items[index].value; | 407 | yield return items[index].value; |
398 | } | 408 | } |
399 | } | 409 | } |
400 | 410 | ||