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;
34 namespace System.Web.Caching
36 sealed partial class CacheItemPriorityQueue
38 const int INITIAL_HEAP_SIZE = 32;
39 const int HEAP_RESIZE_THRESHOLD = 8192;
45 // See comment for the cacheLock field at top of System.Web.Caching/Cache.cs
46 ReaderWriterLockSlim queueLock;
49 get { return heapCount; }
53 get { return heapSize; }
56 public CacheItemPriorityQueue ()
58 queueLock = new ReaderWriterLockSlim ();
62 CacheItem[] GetHeapWithGrow ()
65 heap = new CacheItem [INITIAL_HEAP_SIZE];
66 heapSize = INITIAL_HEAP_SIZE;
71 if (heapCount >= heapSize) {
73 Array.Resize <CacheItem> (ref heap, heapSize);
79 CacheItem[] GetHeapWithShrink ()
84 if (heapSize > HEAP_RESIZE_THRESHOLD) {
85 int halfTheSize = heapSize >> 1;
87 if (heapCount < halfTheSize)
88 Array.Resize <CacheItem> (ref heap, halfTheSize + (heapCount / 3));
94 public void Enqueue (CacheItem item)
102 queueLock.EnterWriteLock ();
103 heap = GetHeapWithGrow ();
104 heap [heapCount++] = item;
107 AddSequenceEntry (item, EDSequenceEntryType.Enqueue);
109 // See comment at the top of the file, above queueLock declaration
110 queueLock.ExitWriteLock ();
114 public CacheItem Dequeue ()
116 CacheItem ret = null;
121 queueLock.EnterWriteLock ();
122 heap = GetHeapWithShrink ();
123 if (heap == null || heapCount == 0)
128 heap [0] = heap [index];
134 AddSequenceEntry (ret, EDSequenceEntryType.Dequeue);
137 // See comment at the top of the file, above queueLock declaration
138 queueLock.ExitWriteLock ();
142 public CacheItem Peek ()
147 queueLock.EnterReadLock ();
148 if (heap == null || heapCount == 0)
152 AddSequenceEntry (ret, EDSequenceEntryType.Peek);
156 // See comment at the top of the file, above queueLock declaration
157 queueLock.ExitReadLock ();
161 void BubbleDown (CacheItem[] heap)
166 CacheItem item = heap [0];
167 int selected = (right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt) ? 2 : 1;
169 while (selected < heapCount && heap [selected].ExpiresAt < item.ExpiresAt) {
170 heap [index] = heap [selected];
172 left = (index << 1) + 1;
174 selected = right < heapCount && heap [right].ExpiresAt < heap [left].ExpiresAt ? right : left;
179 void BubbleUp (CacheItem[] heap)
181 int index, parentIndex;
182 CacheItem parent, item;
187 index = heapCount - 1;
188 parentIndex = (index - 1) >> 1;
192 parent = heap [parentIndex];
193 if (heap [index].ExpiresAt >= parent.ExpiresAt)
196 heap [index] = parent;
198 parentIndex = (index - 1) >> 1;