3 // Marek Habersack <mhabersack@novell.com>
5 // (C) 2009-2010 Novell, Inc (http://novell.com)
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System.Collections.Generic;
31 using System.Threading;
33 namespace System.Runtime.Caching
35 sealed partial class MemoryCacheEntryPriorityQueue
37 const int INITIAL_HEAP_SIZE = 32;
38 const int HEAP_RESIZE_THRESHOLD = 8192;
40 MemoryCacheEntry[] heap;
43 ReaderWriterLockSlim queueLock;
46 get { return heapCount; }
50 get { return heapSize; }
53 public MemoryCacheEntryPriorityQueue ()
55 queueLock = new ReaderWriterLockSlim ();
58 MemoryCacheEntry[] GetHeapWithGrow ()
61 heap = new MemoryCacheEntry [INITIAL_HEAP_SIZE];
62 heapSize = INITIAL_HEAP_SIZE;
67 if (heapCount >= heapSize) {
69 Array.Resize <MemoryCacheEntry> (ref heap, heapSize);
75 MemoryCacheEntry[] GetHeapWithShrink ()
80 if (heapSize > HEAP_RESIZE_THRESHOLD) {
81 int halfTheSize = heapSize >> 1;
83 if (heapCount < halfTheSize)
84 Array.Resize <MemoryCacheEntry> (ref heap, halfTheSize + (heapCount / 3));
90 public void Enqueue (MemoryCacheEntry item)
96 MemoryCacheEntry[] heap;
99 queueLock.EnterWriteLock ();
101 heap = GetHeapWithGrow ();
102 heap [heapCount++] = item;
106 queueLock.ExitWriteLock ();
110 public MemoryCacheEntry Dequeue ()
112 MemoryCacheEntry ret = null;
113 MemoryCacheEntry[] heap;
118 queueLock.EnterWriteLock ();
120 heap = GetHeapWithShrink ();
121 if (heap == null || heapCount == 0)
126 heap [0] = heap [index];
135 queueLock.ExitWriteLock ();
139 public MemoryCacheEntry Peek ()
144 queueLock.EnterReadLock ();
146 if (heap == null || heapCount == 0)
152 queueLock.ExitReadLock ();
156 void BubbleDown (MemoryCacheEntry[] heap)
161 MemoryCacheEntry item = heap [0];
162 int selected = (right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt) ? 2 : 1;
164 while (selected < heapCount && heap [selected].ExpiresAt < item.ExpiresAt) {
165 heap [index] = heap [selected];
167 left = (index << 1) + 1;
169 selected = right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt ? right : left;
174 void BubbleUp (MemoryCacheEntry[] heap)
176 int index, parentIndex;
177 MemoryCacheEntry parent, item;
182 index = heapCount - 1;
183 parentIndex = (index - 1) >> 1;
187 parent = heap [parentIndex];
188 if (heap [index].ExpiresAt >= parent.ExpiresAt)
191 heap [index] = parent;
193 parentIndex = (index - 1) >> 1;