aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/CnmMemoryCache.cs3704
-rw-r--r--OpenSim/Framework/CnmSynchronizedCache.cs1492
-rw-r--r--OpenSim/Framework/ICnmCache.cs882
-rw-r--r--OpenSim/Framework/PrimeNumberHelper.cs196
4 files changed, 3137 insertions, 3137 deletions
diff --git a/OpenSim/Framework/CnmMemoryCache.cs b/OpenSim/Framework/CnmMemoryCache.cs
index 6ca71ec..8c25da0 100644
--- a/OpenSim/Framework/CnmMemoryCache.cs
+++ b/OpenSim/Framework/CnmMemoryCache.cs
@@ -1,1852 +1,1852 @@
1// -------------------------------------------------------------------------------------------------------------------- 1// --------------------------------------------------------------------------------------------------------------------
2// <copyright company="" file="CnmMemoryCache.cs"> 2// <copyright company="" file="CnmMemoryCache.cs">
3// 3//
4// </copyright> 4// </copyright>
5// <summary> 5// <summary>
6// 6//
7// </summary> 7// </summary>
8// -------------------------------------------------------------------------------------------------------------------- 8// --------------------------------------------------------------------------------------------------------------------
9 9
10using System; 10using System;
11using System.Collections; 11using System.Collections;
12using System.Collections.Generic; 12using System.Collections.Generic;
13using System.Diagnostics; 13using System.Diagnostics;
14 14
15namespace OpenSim.Framework 15namespace OpenSim.Framework
16{ 16{
17 /// <summary> 17 /// <summary>
18 /// Cenome memory based cache to store key/value pairs (elements) limited time and/or limited size. 18 /// Cenome memory based cache to store key/value pairs (elements) limited time and/or limited size.
19 /// </summary> 19 /// </summary>
20 /// <typeparam name="TKey"> 20 /// <typeparam name="TKey">
21 /// The type of keys in the cache. 21 /// The type of keys in the cache.
22 /// </typeparam> 22 /// </typeparam>
23 /// <typeparam name="TValue"> 23 /// <typeparam name="TValue">
24 /// The type of values in the dictionary. 24 /// The type of values in the dictionary.
25 /// </typeparam> 25 /// </typeparam>
26 /// <remarks> 26 /// <remarks>
27 /// <para> 27 /// <para>
28 /// Cenome memory cache stores elements to hash table generations. When new element is being added to cache, and new size would exceed 28 /// Cenome memory cache stores elements to hash table generations. When new element is being added to cache, and new size would exceed
29 /// maximal allowed size or maximal amount of allowed element count, then elements in oldest generation are deleted. Last access time 29 /// maximal allowed size or maximal amount of allowed element count, then elements in oldest generation are deleted. Last access time
30 /// is also tracked in generation level - thus it is possible that some elements are staying in cache far beyond their expiration time. 30 /// is also tracked in generation level - thus it is possible that some elements are staying in cache far beyond their expiration time.
31 /// If elements in older generations are accessed through <see cref="TryGetValue"/> method, they are moved to newest generation. 31 /// If elements in older generations are accessed through <see cref="TryGetValue"/> method, they are moved to newest generation.
32 /// </para> 32 /// </para>
33 /// </remarks> 33 /// </remarks>
34 public class CnmMemoryCache<TKey, TValue> : ICnmCache<TKey, TValue> 34 public class CnmMemoryCache<TKey, TValue> : ICnmCache<TKey, TValue>
35 { 35 {
36 /// <summary> 36 /// <summary>
37 /// Default maximal count. 37 /// Default maximal count.
38 /// </summary> 38 /// </summary>
39 /// <seealso cref="MaxCount"/> 39 /// <seealso cref="MaxCount"/>
40 public const int DefaultMaxCount = 4096; 40 public const int DefaultMaxCount = 4096;
41 41
42 /// <summary> 42 /// <summary>
43 /// Default maximal size. 43 /// Default maximal size.
44 /// </summary> 44 /// </summary>
45 /// <remarks> 45 /// <remarks>
46 /// <para> 46 /// <para>
47 /// 128MB = 128 * 1024^2 = 134 217 728 bytes. 47 /// 128MB = 128 * 1024^2 = 134 217 728 bytes.
48 /// </para> 48 /// </para>
49 /// </remarks> 49 /// </remarks>
50 /// <seealso cref="MaxSize"/> 50 /// <seealso cref="MaxSize"/>
51 public const long DefaultMaxSize = 134217728; 51 public const long DefaultMaxSize = 134217728;
52 52
53 /// <summary> 53 /// <summary>
54 /// How many operations between time checks. 54 /// How many operations between time checks.
55 /// </summary> 55 /// </summary>
56 private const int DefaultOperationsBetweenTimeChecks = 40; 56 private const int DefaultOperationsBetweenTimeChecks = 40;
57 57
58 /// <summary> 58 /// <summary>
59 /// Default expiration time. 59 /// Default expiration time.
60 /// </summary> 60 /// </summary>
61 /// <remarks> 61 /// <remarks>
62 /// <para> 62 /// <para>
63 /// 30 minutes. 63 /// 30 minutes.
64 /// </para> 64 /// </para>
65 /// </remarks> 65 /// </remarks>
66 public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 ); 66 public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 );
67 67
68 /// <summary> 68 /// <summary>
69 /// Minimal allowed expiration time. 69 /// Minimal allowed expiration time.
70 /// </summary> 70 /// </summary>
71 /// <remarks> 71 /// <remarks>
72 /// <para> 72 /// <para>
73 /// 5 minutes. 73 /// 5 minutes.
74 /// </para> 74 /// </para>
75 /// </remarks> 75 /// </remarks>
76 public static readonly TimeSpan MinExpirationTime = TimeSpan.FromSeconds( 10.0 ); 76 public static readonly TimeSpan MinExpirationTime = TimeSpan.FromSeconds( 10.0 );
77 77
78 /// <summary> 78 /// <summary>
79 /// Comparer used to compare element keys. 79 /// Comparer used to compare element keys.
80 /// </summary> 80 /// </summary>
81 /// <remarks> 81 /// <remarks>
82 /// Comparer is initialized by constructor. 82 /// Comparer is initialized by constructor.
83 /// </remarks> 83 /// </remarks>
84 /// <seealso cref="CnmMemoryCache{TKey,TValue}"/> 84 /// <seealso cref="CnmMemoryCache{TKey,TValue}"/>
85 public readonly IEqualityComparer<TKey> Comparer; 85 public readonly IEqualityComparer<TKey> Comparer;
86 86
87 /// <summary> 87 /// <summary>
88 /// Expiration time. 88 /// Expiration time.
89 /// </summary> 89 /// </summary>
90 private TimeSpan m_expirationTime = DefaultExpirationTime; 90 private TimeSpan m_expirationTime = DefaultExpirationTime;
91 91
92 /// <summary> 92 /// <summary>
93 /// Generation bucket count. 93 /// Generation bucket count.
94 /// </summary> 94 /// </summary>
95 private int m_generationBucketCount; 95 private int m_generationBucketCount;
96 96
97 /// <summary> 97 /// <summary>
98 /// Generation entry count. 98 /// Generation entry count.
99 /// </summary> 99 /// </summary>
100 private int m_generationElementCount; 100 private int m_generationElementCount;
101 101
102 /// <summary> 102 /// <summary>
103 /// Generation max size. 103 /// Generation max size.
104 /// </summary> 104 /// </summary>
105 private long m_generationMaxSize; 105 private long m_generationMaxSize;
106 106
107 /// <summary> 107 /// <summary>
108 /// Maximal allowed count of elements. 108 /// Maximal allowed count of elements.
109 /// </summary> 109 /// </summary>
110 private int m_maxCount; 110 private int m_maxCount;
111 111
112 /// <summary> 112 /// <summary>
113 /// Maximal allowed total size of elements. 113 /// Maximal allowed total size of elements.
114 /// </summary> 114 /// </summary>
115 private long m_maxElementSize; 115 private long m_maxElementSize;
116 116
117 /// <summary> 117 /// <summary>
118 /// Maximal size. 118 /// Maximal size.
119 /// </summary> 119 /// </summary>
120 private long m_maxSize; 120 private long m_maxSize;
121 121
122 /// <summary> 122 /// <summary>
123 /// New generation. 123 /// New generation.
124 /// </summary> 124 /// </summary>
125 private IGeneration m_newGeneration; 125 private IGeneration m_newGeneration;
126 126
127 /// <summary> 127 /// <summary>
128 /// Old generation. 128 /// Old generation.
129 /// </summary> 129 /// </summary>
130 private IGeneration m_oldGeneration; 130 private IGeneration m_oldGeneration;
131 131
132 /// <summary> 132 /// <summary>
133 /// Operations between time check. 133 /// Operations between time check.
134 /// </summary> 134 /// </summary>
135 private int m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks; 135 private int m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks;
136 136
137 /// <summary> 137 /// <summary>
138 /// Synchronization root object, should always be private and exists always 138 /// Synchronization root object, should always be private and exists always
139 /// </summary> 139 /// </summary>
140 private readonly object m_syncRoot = new object(); 140 private readonly object m_syncRoot = new object();
141 141
142 /// <summary> 142 /// <summary>
143 /// Version of cache. 143 /// Version of cache.
144 /// </summary> 144 /// </summary>
145 /// <remarks> 145 /// <remarks>
146 /// <para> 146 /// <para>
147 /// Updated every time when cache has been changed (element removed, expired, added, replaced). 147 /// Updated every time when cache has been changed (element removed, expired, added, replaced).
148 /// </para> 148 /// </para>
149 /// </remarks> 149 /// </remarks>
150 private int m_version; 150 private int m_version;
151 151
152 /// <summary> 152 /// <summary>
153 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class. 153 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
154 /// </summary> 154 /// </summary>
155 public CnmMemoryCache() 155 public CnmMemoryCache()
156 : this( DefaultMaxSize ) 156 : this( DefaultMaxSize )
157 { 157 {
158 } 158 }
159 159
160 /// <summary> 160 /// <summary>
161 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class. 161 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
162 /// </summary> 162 /// </summary>
163 /// <param name="maximalSize"> 163 /// <param name="maximalSize">
164 /// Maximal cache size. 164 /// Maximal cache size.
165 /// </param> 165 /// </param>
166 public CnmMemoryCache( long maximalSize ) 166 public CnmMemoryCache( long maximalSize )
167 : this( maximalSize, DefaultMaxCount ) 167 : this( maximalSize, DefaultMaxCount )
168 { 168 {
169 } 169 }
170 170
171 /// <summary> 171 /// <summary>
172 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class. 172 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
173 /// </summary> 173 /// </summary>
174 /// <param name="maximalSize"> 174 /// <param name="maximalSize">
175 /// Maximal cache size. 175 /// Maximal cache size.
176 /// </param> 176 /// </param>
177 /// <param name="maximalCount"> 177 /// <param name="maximalCount">
178 /// Maximal element count. 178 /// Maximal element count.
179 /// </param> 179 /// </param>
180 public CnmMemoryCache( long maximalSize, int maximalCount ) 180 public CnmMemoryCache( long maximalSize, int maximalCount )
181 : this( maximalSize, maximalCount, DefaultExpirationTime ) 181 : this( maximalSize, maximalCount, DefaultExpirationTime )
182 { 182 {
183 } 183 }
184 184
185 /// <summary> 185 /// <summary>
186 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class. 186 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
187 /// </summary> 187 /// </summary>
188 /// <param name="maximalSize"> 188 /// <param name="maximalSize">
189 /// Maximal cache size. 189 /// Maximal cache size.
190 /// </param> 190 /// </param>
191 /// <param name="maximalCount"> 191 /// <param name="maximalCount">
192 /// Maximal element count. 192 /// Maximal element count.
193 /// </param> 193 /// </param>
194 /// <param name="expirationTime"> 194 /// <param name="expirationTime">
195 /// Elements expiration time. 195 /// Elements expiration time.
196 /// </param> 196 /// </param>
197 public CnmMemoryCache( long maximalSize, int maximalCount, TimeSpan expirationTime ) 197 public CnmMemoryCache( long maximalSize, int maximalCount, TimeSpan expirationTime )
198 : this( maximalSize, maximalCount, expirationTime, EqualityComparer<TKey>.Default ) 198 : this( maximalSize, maximalCount, expirationTime, EqualityComparer<TKey>.Default )
199 { 199 {
200 } 200 }
201 201
202 /// <summary> 202 /// <summary>
203 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class. 203 /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
204 /// </summary> 204 /// </summary>
205 /// <param name="maximalSize"> 205 /// <param name="maximalSize">
206 /// Maximal cache size. 206 /// Maximal cache size.
207 /// </param> 207 /// </param>
208 /// <param name="maximalCount"> 208 /// <param name="maximalCount">
209 /// Maximal element count. 209 /// Maximal element count.
210 /// </param> 210 /// </param>
211 /// <param name="expirationTime"> 211 /// <param name="expirationTime">
212 /// Elements expiration time. 212 /// Elements expiration time.
213 /// </param> 213 /// </param>
214 /// <param name="comparer"> 214 /// <param name="comparer">
215 /// Comparer used for comparing elements. 215 /// Comparer used for comparing elements.
216 /// </param> 216 /// </param>
217 /// <exception cref="ArgumentNullException"> 217 /// <exception cref="ArgumentNullException">
218 /// <see cref="comparer"/>is <see langword="null"/> reference. 218 /// <see cref="comparer"/>is <see langword="null"/> reference.
219 /// </exception> 219 /// </exception>
220 public CnmMemoryCache( long maximalSize, 220 public CnmMemoryCache( long maximalSize,
221 int maximalCount, 221 int maximalCount,
222 TimeSpan expirationTime, 222 TimeSpan expirationTime,
223 IEqualityComparer<TKey> comparer ) 223 IEqualityComparer<TKey> comparer )
224 { 224 {
225 if( comparer == null ) 225 if( comparer == null )
226 throw new ArgumentNullException( "comparer" ); 226 throw new ArgumentNullException( "comparer" );
227 227
228 if( expirationTime < MinExpirationTime ) 228 if( expirationTime < MinExpirationTime )
229 expirationTime = MinExpirationTime; 229 expirationTime = MinExpirationTime;
230 if( maximalCount < 8 ) 230 if( maximalCount < 8 )
231 maximalCount = 8; 231 maximalCount = 8;
232 if( maximalSize < 8 ) 232 if( maximalSize < 8 )
233 maximalSize = 8; 233 maximalSize = 8;
234 if( maximalCount > maximalSize ) 234 if( maximalCount > maximalSize )
235 maximalCount = (int) maximalSize; 235 maximalCount = (int) maximalSize;
236 236
237 Comparer = comparer; 237 Comparer = comparer;
238 m_expirationTime = expirationTime; 238 m_expirationTime = expirationTime;
239 m_maxSize = maximalSize; 239 m_maxSize = maximalSize;
240 m_maxCount = maximalCount; 240 m_maxCount = maximalCount;
241 241
242 Initialize(); 242 Initialize();
243 } 243 }
244 244
245 /// <summary> 245 /// <summary>
246 /// Add element to new generation. 246 /// Add element to new generation.
247 /// </summary> 247 /// </summary>
248 /// <param name="bucketIndex"> 248 /// <param name="bucketIndex">
249 /// The bucket index. 249 /// The bucket index.
250 /// </param> 250 /// </param>
251 /// <param name="key"> 251 /// <param name="key">
252 /// The element's key. 252 /// The element's key.
253 /// </param> 253 /// </param>
254 /// <param name="value"> 254 /// <param name="value">
255 /// The element's value. 255 /// The element's value.
256 /// </param> 256 /// </param>
257 /// <param name="size"> 257 /// <param name="size">
258 /// The element's size. 258 /// The element's size.
259 /// </param> 259 /// </param>
260 protected virtual void AddToNewGeneration( int bucketIndex, TKey key, TValue value, long size ) 260 protected virtual void AddToNewGeneration( int bucketIndex, TKey key, TValue value, long size )
261 { 261 {
262 // Add to newest generation 262 // Add to newest generation
263 if( !m_newGeneration.Set( bucketIndex, key, value, size ) ) 263 if( !m_newGeneration.Set( bucketIndex, key, value, size ) )
264 { 264 {
265 // Failed to add new generation 265 // Failed to add new generation
266 RecycleGenerations(); 266 RecycleGenerations();
267 m_newGeneration.Set( bucketIndex, key, value, size ); 267 m_newGeneration.Set( bucketIndex, key, value, size );
268 } 268 }
269 269
270 m_version++; 270 m_version++;
271 } 271 }
272 272
273 /// <summary> 273 /// <summary>
274 /// <para> 274 /// <para>
275 /// Get keys bucket index. 275 /// Get keys bucket index.
276 /// </para> 276 /// </para>
277 /// </summary> 277 /// </summary>
278 /// <param name="key"> 278 /// <param name="key">
279 /// <para> 279 /// <para>
280 /// Key which bucket index is being retrieved. 280 /// Key which bucket index is being retrieved.
281 /// </para> 281 /// </para>
282 /// </param> 282 /// </param>
283 /// <returns> 283 /// <returns>
284 /// <para> 284 /// <para>
285 /// Bucket index. 285 /// Bucket index.
286 /// </para> 286 /// </para>
287 /// </returns> 287 /// </returns>
288 /// <remarks> 288 /// <remarks>
289 /// <para> 289 /// <para>
290 /// Method uses <see cref="Comparer"/> to calculate <see cref="key"/> hash code. 290 /// Method uses <see cref="Comparer"/> to calculate <see cref="key"/> hash code.
291 /// </para> 291 /// </para>
292 /// <para> 292 /// <para>
293 /// Bucket index is remainder when element key's hash value is divided by bucket count. 293 /// Bucket index is remainder when element key's hash value is divided by bucket count.
294 /// </para> 294 /// </para>
295 /// <para> 295 /// <para>
296 /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2. 296 /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2.
297 /// </para> 297 /// </para>
298 /// </remarks> 298 /// </remarks>
299 protected virtual int GetBucketIndex( TKey key ) 299 protected virtual int GetBucketIndex( TKey key )
300 { 300 {
301 return (Comparer.GetHashCode( key ) & 0x7FFFFFFF) % m_generationBucketCount; 301 return (Comparer.GetHashCode( key ) & 0x7FFFFFFF) % m_generationBucketCount;
302 } 302 }
303 303
304 /// <summary> 304 /// <summary>
305 /// Purge generation from the cache. 305 /// Purge generation from the cache.
306 /// </summary> 306 /// </summary>
307 /// <param name="generation"> 307 /// <param name="generation">
308 /// The generation that is purged. 308 /// The generation that is purged.
309 /// </param> 309 /// </param>
310 protected virtual void PurgeGeneration( IGeneration generation ) 310 protected virtual void PurgeGeneration( IGeneration generation )
311 { 311 {
312 generation.Clear(); 312 generation.Clear();
313 m_version++; 313 m_version++;
314 } 314 }
315 315
316 /// <summary> 316 /// <summary>
317 /// check expired. 317 /// check expired.
318 /// </summary> 318 /// </summary>
319 private void CheckExpired() 319 private void CheckExpired()
320 { 320 {
321 // Do this only one in every m_operationsBetweenTimeChecks 321 // Do this only one in every m_operationsBetweenTimeChecks
322 // Fetching time is using several millisecons - it is better not to do all time. 322 // Fetching time is using several millisecons - it is better not to do all time.
323 m_operationsBetweenTimeChecks--; 323 m_operationsBetweenTimeChecks--;
324 if( m_operationsBetweenTimeChecks <= 0 ) 324 if( m_operationsBetweenTimeChecks <= 0 )
325 PurgeExpired(); 325 PurgeExpired();
326 } 326 }
327 327
328 /// <summary> 328 /// <summary>
329 /// Initialize cache. 329 /// Initialize cache.
330 /// </summary> 330 /// </summary>
331 private void Initialize() 331 private void Initialize()
332 { 332 {
333 m_version++; 333 m_version++;
334 334
335 m_generationMaxSize = MaxSize / 2; 335 m_generationMaxSize = MaxSize / 2;
336 MaxElementSize = MaxSize / 8; 336 MaxElementSize = MaxSize / 8;
337 m_generationElementCount = MaxCount / 2; 337 m_generationElementCount = MaxCount / 2;
338 338
339 // Buckets need to be prime number to get better spread of hash values 339 // Buckets need to be prime number to get better spread of hash values
340 m_generationBucketCount = PrimeNumberHelper.GetPrime( m_generationElementCount ); 340 m_generationBucketCount = PrimeNumberHelper.GetPrime( m_generationElementCount );
341 341
342 m_newGeneration = new HashGeneration( this ); 342 m_newGeneration = new HashGeneration( this );
343 m_oldGeneration = new HashGeneration( this ); 343 m_oldGeneration = new HashGeneration( this );
344 m_oldGeneration.MakeOld(); 344 m_oldGeneration.MakeOld();
345 } 345 }
346 346
347 /// <summary> 347 /// <summary>
348 /// Recycle generations. 348 /// Recycle generations.
349 /// </summary> 349 /// </summary>
350 private void RecycleGenerations() 350 private void RecycleGenerations()
351 { 351 {
352 // Rotate old generation to new generation, new generation to old generation 352 // Rotate old generation to new generation, new generation to old generation
353 IGeneration temp = m_newGeneration; 353 IGeneration temp = m_newGeneration;
354 m_newGeneration = m_oldGeneration; 354 m_newGeneration = m_oldGeneration;
355 m_newGeneration.Clear(); 355 m_newGeneration.Clear();
356 m_oldGeneration = temp; 356 m_oldGeneration = temp;
357 m_oldGeneration.MakeOld(); 357 m_oldGeneration.MakeOld();
358 } 358 }
359 359
360 #region Nested type: Enumerator 360 #region Nested type: Enumerator
361 361
362 /// <summary> 362 /// <summary>
363 /// Key and value pair enumerator. 363 /// Key and value pair enumerator.
364 /// </summary> 364 /// </summary>
365 private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> 365 private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
366 { 366 {
367 /// <summary> 367 /// <summary>
368 /// Current enumerator. 368 /// Current enumerator.
369 /// </summary> 369 /// </summary>
370 private int m_currentEnumerator = -1; 370 private int m_currentEnumerator = -1;
371 371
372 /// <summary> 372 /// <summary>
373 /// Enumerators to different generations. 373 /// Enumerators to different generations.
374 /// </summary> 374 /// </summary>
375 private readonly IEnumerator<KeyValuePair<TKey, TValue>>[] m_generationEnumerators = 375 private readonly IEnumerator<KeyValuePair<TKey, TValue>>[] m_generationEnumerators =
376 new IEnumerator<KeyValuePair<TKey, TValue>>[2]; 376 new IEnumerator<KeyValuePair<TKey, TValue>>[2];
377 377
378 /// <summary> 378 /// <summary>
379 /// Initializes a new instance of the <see cref="Enumerator"/> class. 379 /// Initializes a new instance of the <see cref="Enumerator"/> class.
380 /// </summary> 380 /// </summary>
381 /// <param name="cache"> 381 /// <param name="cache">
382 /// The cache. 382 /// The cache.
383 /// </param> 383 /// </param>
384 public Enumerator( CnmMemoryCache<TKey, TValue> cache ) 384 public Enumerator( CnmMemoryCache<TKey, TValue> cache )
385 { 385 {
386 m_generationEnumerators[ 0 ] = cache.m_newGeneration.GetEnumerator(); 386 m_generationEnumerators[ 0 ] = cache.m_newGeneration.GetEnumerator();
387 m_generationEnumerators[ 1 ] = cache.m_oldGeneration.GetEnumerator(); 387 m_generationEnumerators[ 1 ] = cache.m_oldGeneration.GetEnumerator();
388 } 388 }
389 389
390 #region IEnumerator<KeyValuePair<TKey,TValue>> Members 390 #region IEnumerator<KeyValuePair<TKey,TValue>> Members
391 391
392 /// <summary> 392 /// <summary>
393 /// Gets the element in the collection at the current position of the enumerator. 393 /// Gets the element in the collection at the current position of the enumerator.
394 /// </summary> 394 /// </summary>
395 /// <returns> 395 /// <returns>
396 /// The element in the collection at the current position of the enumerator. 396 /// The element in the collection at the current position of the enumerator.
397 /// </returns> 397 /// </returns>
398 /// <exception cref="InvalidOperationException"> 398 /// <exception cref="InvalidOperationException">
399 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called. 399 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
400 /// </exception> 400 /// </exception>
401 public KeyValuePair<TKey, TValue> Current 401 public KeyValuePair<TKey, TValue> Current
402 { 402 {
403 get 403 get
404 { 404 {
405 if( m_currentEnumerator == -1 || m_currentEnumerator >= m_generationEnumerators.Length ) 405 if( m_currentEnumerator == -1 || m_currentEnumerator >= m_generationEnumerators.Length )
406 throw new InvalidOperationException(); 406 throw new InvalidOperationException();
407 407
408 return m_generationEnumerators[ m_currentEnumerator ].Current; 408 return m_generationEnumerators[ m_currentEnumerator ].Current;
409 } 409 }
410 } 410 }
411 411
412 /// <summary> 412 /// <summary>
413 /// Gets the current element in the collection. 413 /// Gets the current element in the collection.
414 /// </summary> 414 /// </summary>
415 /// <returns> 415 /// <returns>
416 /// The current element in the collection. 416 /// The current element in the collection.
417 /// </returns> 417 /// </returns>
418 /// <exception cref="T:System.InvalidOperationException"> 418 /// <exception cref="T:System.InvalidOperationException">
419 /// The enumerator is positioned before the first element of the collection or after the last element. 419 /// The enumerator is positioned before the first element of the collection or after the last element.
420 /// </exception><filterpriority>2</filterpriority> 420 /// </exception><filterpriority>2</filterpriority>
421 object IEnumerator.Current 421 object IEnumerator.Current
422 { 422 {
423 get { return Current; } 423 get { return Current; }
424 } 424 }
425 425
426 /// <summary> 426 /// <summary>
427 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 427 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
428 /// </summary> 428 /// </summary>
429 /// <filterpriority>2</filterpriority> 429 /// <filterpriority>2</filterpriority>
430 public void Dispose() 430 public void Dispose()
431 { 431 {
432 } 432 }
433 433
434 /// <summary> 434 /// <summary>
435 /// Advances the enumerator to the next element of the collection. 435 /// Advances the enumerator to the next element of the collection.
436 /// </summary> 436 /// </summary>
437 /// <returns> 437 /// <returns>
438 /// <see langword="true"/>if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection. 438 /// <see langword="true"/>if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.
439 /// </returns> 439 /// </returns>
440 /// <exception cref="T:System.InvalidOperationException"> 440 /// <exception cref="T:System.InvalidOperationException">
441 /// The collection was modified after the enumerator was created. 441 /// The collection was modified after the enumerator was created.
442 /// </exception> 442 /// </exception>
443 /// <filterpriority>2</filterpriority> 443 /// <filterpriority>2</filterpriority>
444 public bool MoveNext() 444 public bool MoveNext()
445 { 445 {
446 if( m_currentEnumerator == -1 ) 446 if( m_currentEnumerator == -1 )
447 m_currentEnumerator = 0; 447 m_currentEnumerator = 0;
448 448
449 while( m_currentEnumerator < m_generationEnumerators.Length ) 449 while( m_currentEnumerator < m_generationEnumerators.Length )
450 { 450 {
451 if( m_generationEnumerators[ m_currentEnumerator ].MoveNext() ) 451 if( m_generationEnumerators[ m_currentEnumerator ].MoveNext() )
452 return true; 452 return true;
453 453
454 m_currentEnumerator++; 454 m_currentEnumerator++;
455 } 455 }
456 456
457 return false; 457 return false;
458 } 458 }
459 459
460 /// <summary> 460 /// <summary>
461 /// Sets the enumerator to its initial position, which is before the first element in the collection. 461 /// Sets the enumerator to its initial position, which is before the first element in the collection.
462 /// </summary> 462 /// </summary>
463 /// <exception cref="T:System.InvalidOperationException"> 463 /// <exception cref="T:System.InvalidOperationException">
464 /// The collection was modified after the enumerator was created. 464 /// The collection was modified after the enumerator was created.
465 /// </exception> 465 /// </exception>
466 /// <filterpriority>2</filterpriority> 466 /// <filterpriority>2</filterpriority>
467 public void Reset() 467 public void Reset()
468 { 468 {
469 foreach( IEnumerator<KeyValuePair<TKey, TValue>> enumerator in m_generationEnumerators ) 469 foreach( IEnumerator<KeyValuePair<TKey, TValue>> enumerator in m_generationEnumerators )
470 { 470 {
471 enumerator.Reset(); 471 enumerator.Reset();
472 } 472 }
473 473
474 m_currentEnumerator = -1; 474 m_currentEnumerator = -1;
475 } 475 }
476 476
477 #endregion 477 #endregion
478 } 478 }
479 479
480 #endregion 480 #endregion
481 481
482 #region Nested type: HashGeneration 482 #region Nested type: HashGeneration
483 483
484 /// <summary> 484 /// <summary>
485 /// Hash generation class 485 /// Hash generation class
486 /// </summary> 486 /// </summary>
487 /// <remarks> 487 /// <remarks>
488 /// <para> 488 /// <para>
489 /// Current implementation is based to separated chaining with move-to-front heuristics. Hash generations have fixed 489 /// Current implementation is based to separated chaining with move-to-front heuristics. Hash generations have fixed
490 /// amount of buckets and it is never rehashed. 490 /// amount of buckets and it is never rehashed.
491 /// </para> 491 /// </para>
492 /// <para> 492 /// <para>
493 /// Read more about hash tables from <a href="http://en.wikipedia.org/wiki/Hash_table">Wiki article</a>. 493 /// Read more about hash tables from <a href="http://en.wikipedia.org/wiki/Hash_table">Wiki article</a>.
494 /// </para> 494 /// </para>
495 /// </remarks> 495 /// </remarks>
496 /// <seealso href="http://en.wikipedia.org/wiki/Hash_table"/> 496 /// <seealso href="http://en.wikipedia.org/wiki/Hash_table"/>
497 private class HashGeneration : IGeneration 497 private class HashGeneration : IGeneration
498 { 498 {
499 /// <summary> 499 /// <summary>
500 /// Value indicating whether generation was accessed since last time check. 500 /// Value indicating whether generation was accessed since last time check.
501 /// </summary> 501 /// </summary>
502 private bool m_accessedSinceLastTimeCheck; 502 private bool m_accessedSinceLastTimeCheck;
503 503
504 /// <summary> 504 /// <summary>
505 /// Index of first element's in element chain. 505 /// Index of first element's in element chain.
506 /// </summary> 506 /// </summary>
507 /// <value> 507 /// <value>
508 /// -1 if there is no element in bucket; otherwise first element's index in the element chain. 508 /// -1 if there is no element in bucket; otherwise first element's index in the element chain.
509 /// </value> 509 /// </value>
510 /// <remarks> 510 /// <remarks>
511 /// Bucket index is remainder when element key's hash value is divided by bucket count. 511 /// Bucket index is remainder when element key's hash value is divided by bucket count.
512 /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2. 512 /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2.
513 /// </remarks> 513 /// </remarks>
514 private readonly int[] m_buckets; 514 private readonly int[] m_buckets;
515 515
516 /// <summary> 516 /// <summary>
517 /// Cache object. 517 /// Cache object.
518 /// </summary> 518 /// </summary>
519 private readonly CnmMemoryCache<TKey, TValue> m_cache; 519 private readonly CnmMemoryCache<TKey, TValue> m_cache;
520 520
521 /// <summary> 521 /// <summary>
522 /// Generation's element array. 522 /// Generation's element array.
523 /// </summary> 523 /// </summary>
524 /// <seealso cref="Element"/> 524 /// <seealso cref="Element"/>
525 private readonly Element[] m_elements; 525 private readonly Element[] m_elements;
526 526
527 /// <summary> 527 /// <summary>
528 /// Generation's expiration time. 528 /// Generation's expiration time.
529 /// </summary> 529 /// </summary>
530 private DateTime m_expirationTime1; 530 private DateTime m_expirationTime1;
531 531
532 /// <summary> 532 /// <summary>
533 /// Index to first free element. 533 /// Index to first free element.
534 /// </summary> 534 /// </summary>
535 private int m_firstFreeElement; 535 private int m_firstFreeElement;
536 536
537 /// <summary> 537 /// <summary>
538 /// Free element count. 538 /// Free element count.
539 /// </summary> 539 /// </summary>
540 /// <remarks> 540 /// <remarks>
541 /// When generation is cleared or constructed, this is NOT set to element count. 541 /// When generation is cleared or constructed, this is NOT set to element count.
542 /// This is only tracking elements that are removed and are currently free. 542 /// This is only tracking elements that are removed and are currently free.
543 /// </remarks> 543 /// </remarks>
544 private int m_freeCount; 544 private int m_freeCount;
545 545
546 /// <summary> 546 /// <summary>
547 /// Is this generation "new generation". 547 /// Is this generation "new generation".
548 /// </summary> 548 /// </summary>
549 private bool m_newGeneration; 549 private bool m_newGeneration;
550 550
551 /// <summary> 551 /// <summary>
552 /// Next unused entry. 552 /// Next unused entry.
553 /// </summary> 553 /// </summary>
554 private int m_nextUnusedElement; 554 private int m_nextUnusedElement;
555 555
556 /// <summary> 556 /// <summary>
557 /// Size of data stored to generation. 557 /// Size of data stored to generation.
558 /// </summary> 558 /// </summary>
559 private long m_size; 559 private long m_size;
560 560
561 /// <summary> 561 /// <summary>
562 /// Initializes a new instance of the <see cref="HashGeneration"/> class. 562 /// Initializes a new instance of the <see cref="HashGeneration"/> class.
563 /// </summary> 563 /// </summary>
564 /// <param name="cache"> 564 /// <param name="cache">
565 /// The cache. 565 /// The cache.
566 /// </param> 566 /// </param>
567 public HashGeneration( CnmMemoryCache<TKey, TValue> cache ) 567 public HashGeneration( CnmMemoryCache<TKey, TValue> cache )
568 { 568 {
569 m_cache = cache; 569 m_cache = cache;
570 m_elements = new Element[m_cache.m_generationElementCount]; 570 m_elements = new Element[m_cache.m_generationElementCount];
571 m_buckets = new int[m_cache.m_generationBucketCount]; 571 m_buckets = new int[m_cache.m_generationBucketCount];
572 Clear(); 572 Clear();
573 } 573 }
574 574
575 /// <summary> 575 /// <summary>
576 /// Find element's index 576 /// Find element's index
577 /// </summary> 577 /// </summary>
578 /// <param name="bucketIndex"> 578 /// <param name="bucketIndex">
579 /// The element's bucket index. 579 /// The element's bucket index.
580 /// </param> 580 /// </param>
581 /// <param name="key"> 581 /// <param name="key">
582 /// The element's key. 582 /// The element's key.
583 /// </param> 583 /// </param>
584 /// <param name="moveToFront"> 584 /// <param name="moveToFront">
585 /// Move element to front of elements. 585 /// Move element to front of elements.
586 /// </param> 586 /// </param>
587 /// <param name="previousIndex"> 587 /// <param name="previousIndex">
588 /// The previous element's index. 588 /// The previous element's index.
589 /// </param> 589 /// </param>
590 /// <returns> 590 /// <returns>
591 /// Element's index, if found from the generation; -1 otherwise (if element is not found the generation). 591 /// Element's index, if found from the generation; -1 otherwise (if element is not found the generation).
592 /// </returns> 592 /// </returns>
593 private int FindElementIndex( int bucketIndex, TKey key, bool moveToFront, out int previousIndex ) 593 private int FindElementIndex( int bucketIndex, TKey key, bool moveToFront, out int previousIndex )
594 { 594 {
595 previousIndex = -1; 595 previousIndex = -1;
596 int elementIndex = m_buckets[ bucketIndex ]; 596 int elementIndex = m_buckets[ bucketIndex ];
597 while( elementIndex >= 0 ) 597 while( elementIndex >= 0 )
598 { 598 {
599 if( m_cache.Comparer.Equals( key, m_elements[ elementIndex ].Key ) ) 599 if( m_cache.Comparer.Equals( key, m_elements[ elementIndex ].Key ) )
600 { 600 {
601 // Found match 601 // Found match
602 if( moveToFront && previousIndex >= 0 ) 602 if( moveToFront && previousIndex >= 0 )
603 { 603 {
604 // Move entry to front 604 // Move entry to front
605 m_elements[ previousIndex ].Next = m_elements[ elementIndex ].Next; 605 m_elements[ previousIndex ].Next = m_elements[ elementIndex ].Next;
606 m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ]; 606 m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ];
607 m_buckets[ bucketIndex ] = elementIndex; 607 m_buckets[ bucketIndex ] = elementIndex;
608 previousIndex = 0; 608 previousIndex = 0;
609 } 609 }
610 610
611 return elementIndex; 611 return elementIndex;
612 } 612 }
613 613
614 previousIndex = elementIndex; 614 previousIndex = elementIndex;
615 elementIndex = m_elements[ elementIndex ].Next; 615 elementIndex = m_elements[ elementIndex ].Next;
616 } 616 }
617 617
618 return -1; 618 return -1;
619 } 619 }
620 620
621 /// <summary> 621 /// <summary>
622 /// Remove element front the generation. 622 /// Remove element front the generation.
623 /// </summary> 623 /// </summary>
624 /// <param name="bucketIndex"> 624 /// <param name="bucketIndex">
625 /// The bucket index. 625 /// The bucket index.
626 /// </param> 626 /// </param>
627 /// <param name="entryIndex"> 627 /// <param name="entryIndex">
628 /// The element index. 628 /// The element index.
629 /// </param> 629 /// </param>
630 /// <param name="previousIndex"> 630 /// <param name="previousIndex">
631 /// The element's previous index. 631 /// The element's previous index.
632 /// </param> 632 /// </param>
633 private void RemoveElement( int bucketIndex, int entryIndex, int previousIndex ) 633 private void RemoveElement( int bucketIndex, int entryIndex, int previousIndex )
634 { 634 {
635 if( previousIndex >= 0 ) 635 if( previousIndex >= 0 )
636 m_elements[ previousIndex ].Next = m_elements[ entryIndex ].Next; 636 m_elements[ previousIndex ].Next = m_elements[ entryIndex ].Next;
637 else 637 else
638 m_buckets[ bucketIndex ] = m_elements[ entryIndex ].Next; 638 m_buckets[ bucketIndex ] = m_elements[ entryIndex ].Next;
639 639
640 Size -= m_elements[ entryIndex ].Size; 640 Size -= m_elements[ entryIndex ].Size;
641 m_elements[ entryIndex ].Value = default(TValue); 641 m_elements[ entryIndex ].Value = default(TValue);
642 m_elements[ entryIndex ].Key = default(TKey); 642 m_elements[ entryIndex ].Key = default(TKey);
643 643
644 // Add element to free elements list 644 // Add element to free elements list
645 m_elements[ entryIndex ].Next = m_firstFreeElement; 645 m_elements[ entryIndex ].Next = m_firstFreeElement;
646 m_firstFreeElement = entryIndex; 646 m_firstFreeElement = entryIndex;
647 m_freeCount++; 647 m_freeCount++;
648 } 648 }
649 649
650 #region Nested type: Element 650 #region Nested type: Element
651 651
652 /// <summary> 652 /// <summary>
653 /// Element that stores key, next element in chain, size and value. 653 /// Element that stores key, next element in chain, size and value.
654 /// </summary> 654 /// </summary>
655 private struct Element 655 private struct Element
656 { 656 {
657 /// <summary> 657 /// <summary>
658 /// Element's key. 658 /// Element's key.
659 /// </summary> 659 /// </summary>
660 public TKey Key; 660 public TKey Key;
661 661
662 /// <summary> 662 /// <summary>
663 /// Next element in chain. 663 /// Next element in chain.
664 /// </summary> 664 /// </summary>
665 /// <remarks> 665 /// <remarks>
666 /// When element have value (something is stored to it), this is index of 666 /// When element have value (something is stored to it), this is index of
667 /// next element with same bucket index. When element is free, this 667 /// next element with same bucket index. When element is free, this
668 /// is index of next element in free element's list. 668 /// is index of next element in free element's list.
669 /// </remarks> 669 /// </remarks>
670 public int Next; 670 public int Next;
671 671
672 /// <summary> 672 /// <summary>
673 /// Size of element. 673 /// Size of element.
674 /// </summary> 674 /// </summary>
675 /// <value> 675 /// <value>
676 /// 0 if element is free; otherwise larger than 0. 676 /// 0 if element is free; otherwise larger than 0.
677 /// </value> 677 /// </value>
678 public long Size; 678 public long Size;
679 679
680 /// <summary> 680 /// <summary>
681 /// Element's value. 681 /// Element's value.
682 /// </summary> 682 /// </summary>
683 /// <remarks> 683 /// <remarks>
684 /// It is possible that this value is <see langword="null"/> even when element 684 /// It is possible that this value is <see langword="null"/> even when element
685 /// have value - element's value is then <see langword="null"/> reference. 685 /// have value - element's value is then <see langword="null"/> reference.
686 /// </remarks> 686 /// </remarks>
687 public TValue Value; 687 public TValue Value;
688 688
689 /// <summary> 689 /// <summary>
690 /// Gets a value indicating whether element is free or have value. 690 /// Gets a value indicating whether element is free or have value.
691 /// </summary> 691 /// </summary>
692 /// <value> 692 /// <value>
693 /// <see langword="true"/> when element is free; otherwise <see langword="false"/>. 693 /// <see langword="true"/> when element is free; otherwise <see langword="false"/>.
694 /// </value> 694 /// </value>
695 public bool IsFree 695 public bool IsFree
696 { 696 {
697 get { return Size == 0; } 697 get { return Size == 0; }
698 } 698 }
699 } 699 }
700 700
701 #endregion 701 #endregion
702 702
703 #region Nested type: Enumerator 703 #region Nested type: Enumerator
704 704
705 /// <summary> 705 /// <summary>
706 /// Key value pair enumerator for <see cref="HashGeneration"/> object. 706 /// Key value pair enumerator for <see cref="HashGeneration"/> object.
707 /// </summary> 707 /// </summary>
708 private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> 708 private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
709 { 709 {
710 /// <summary> 710 /// <summary>
711 /// Current element. 711 /// Current element.
712 /// </summary> 712 /// </summary>
713 private KeyValuePair<TKey, TValue> m_current; 713 private KeyValuePair<TKey, TValue> m_current;
714 714
715 /// <summary> 715 /// <summary>
716 /// Current index. 716 /// Current index.
717 /// </summary> 717 /// </summary>
718 private int m_currentIndex; 718 private int m_currentIndex;
719 719
720 /// <summary> 720 /// <summary>
721 /// Generation that is being enumerated. 721 /// Generation that is being enumerated.
722 /// </summary> 722 /// </summary>
723 private readonly HashGeneration m_generation; 723 private readonly HashGeneration m_generation;
724 724
725 /// <summary> 725 /// <summary>
726 /// Cache version. 726 /// Cache version.
727 /// </summary> 727 /// </summary>
728 /// <remarks> 728 /// <remarks>
729 /// When cache is change, version number is changed. 729 /// When cache is change, version number is changed.
730 /// </remarks> 730 /// </remarks>
731 /// <seealso cref="CnmMemoryCache{TKey,TValue}.m_version"/> 731 /// <seealso cref="CnmMemoryCache{TKey,TValue}.m_version"/>
732 private readonly int m_version; 732 private readonly int m_version;
733 733
734 /// <summary> 734 /// <summary>
735 /// Initializes a new instance of the <see cref="Enumerator"/> class. 735 /// Initializes a new instance of the <see cref="Enumerator"/> class.
736 /// </summary> 736 /// </summary>
737 /// <param name="generation"> 737 /// <param name="generation">
738 /// The generation. 738 /// The generation.
739 /// </param> 739 /// </param>
740 public Enumerator( HashGeneration generation ) 740 public Enumerator( HashGeneration generation )
741 { 741 {
742 m_generation = generation; 742 m_generation = generation;
743 m_version = m_generation.m_cache.m_version; 743 m_version = m_generation.m_cache.m_version;
744 } 744 }
745 745
746 #region IEnumerator<KeyValuePair<TKey,TValue>> Members 746 #region IEnumerator<KeyValuePair<TKey,TValue>> Members
747 747
748 /// <summary> 748 /// <summary>
749 /// Gets the element in the collection at the current position of the enumerator. 749 /// Gets the element in the collection at the current position of the enumerator.
750 /// </summary> 750 /// </summary>
751 /// <returns> 751 /// <returns>
752 /// The element in the collection at the current position of the enumerator. 752 /// The element in the collection at the current position of the enumerator.
753 /// </returns> 753 /// </returns>
754 /// <exception cref="InvalidOperationException"> 754 /// <exception cref="InvalidOperationException">
755 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called. 755 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
756 /// </exception> 756 /// </exception>
757 public KeyValuePair<TKey, TValue> Current 757 public KeyValuePair<TKey, TValue> Current
758 { 758 {
759 get 759 get
760 { 760 {
761 if( m_currentIndex == 0 || m_currentIndex >= m_generation.Count ) 761 if( m_currentIndex == 0 || m_currentIndex >= m_generation.Count )
762 throw new InvalidOperationException(); 762 throw new InvalidOperationException();
763 763
764 return m_current; 764 return m_current;
765 } 765 }
766 } 766 }
767 767
768 /// <summary> 768 /// <summary>
769 /// Gets the current element in the collection. 769 /// Gets the current element in the collection.
770 /// </summary> 770 /// </summary>
771 /// <returns> 771 /// <returns>
772 /// The current element in the collection. 772 /// The current element in the collection.
773 /// </returns> 773 /// </returns>
774 /// <exception cref="InvalidOperationException"> 774 /// <exception cref="InvalidOperationException">
775 /// The enumerator is positioned before the first element of the collection or after the last element. 775 /// The enumerator is positioned before the first element of the collection or after the last element.
776 /// </exception><filterpriority>2</filterpriority> 776 /// </exception><filterpriority>2</filterpriority>
777 object IEnumerator.Current 777 object IEnumerator.Current
778 { 778 {
779 get { return Current; } 779 get { return Current; }
780 } 780 }
781 781
782 /// <summary> 782 /// <summary>
783 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 783 /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
784 /// </summary> 784 /// </summary>
785 /// <filterpriority>2</filterpriority> 785 /// <filterpriority>2</filterpriority>
786 public void Dispose() 786 public void Dispose()
787 { 787 {
788 } 788 }
789 789
790 /// <summary> 790 /// <summary>
791 /// Advances the enumerator to the next element of the collection. 791 /// Advances the enumerator to the next element of the collection.
792 /// </summary> 792 /// </summary>
793 /// <returns> 793 /// <returns>
794 /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. 794 /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
795 /// </returns> 795 /// </returns>
796 /// <exception cref="InvalidOperationException"> 796 /// <exception cref="InvalidOperationException">
797 /// The collection was modified after the enumerator was created. 797 /// The collection was modified after the enumerator was created.
798 /// </exception> 798 /// </exception>
799 public bool MoveNext() 799 public bool MoveNext()
800 { 800 {
801 if( m_version != m_generation.m_cache.m_version ) 801 if( m_version != m_generation.m_cache.m_version )
802 throw new InvalidOperationException(); 802 throw new InvalidOperationException();
803 803
804 while( m_currentIndex < m_generation.Count ) 804 while( m_currentIndex < m_generation.Count )
805 { 805 {
806 if( m_generation.m_elements[ m_currentIndex ].IsFree ) 806 if( m_generation.m_elements[ m_currentIndex ].IsFree )
807 { 807 {
808 m_currentIndex++; 808 m_currentIndex++;
809 continue; 809 continue;
810 } 810 }
811 811
812 m_current = new KeyValuePair<TKey, TValue>( m_generation.m_elements[ m_currentIndex ].Key, 812 m_current = new KeyValuePair<TKey, TValue>( m_generation.m_elements[ m_currentIndex ].Key,
813 m_generation.m_elements[ m_currentIndex ].Value ); 813 m_generation.m_elements[ m_currentIndex ].Value );
814 m_currentIndex++; 814 m_currentIndex++;
815 return true; 815 return true;
816 } 816 }
817 817
818 m_current = new KeyValuePair<TKey, TValue>(); 818 m_current = new KeyValuePair<TKey, TValue>();
819 return false; 819 return false;
820 } 820 }
821 821
822 /// <summary> 822 /// <summary>
823 /// Sets the enumerator to its initial position, which is before the first element in the collection. 823 /// Sets the enumerator to its initial position, which is before the first element in the collection.
824 /// </summary> 824 /// </summary>
825 /// <exception cref="InvalidOperationException"> 825 /// <exception cref="InvalidOperationException">
826 /// The collection was modified after the enumerator was created. 826 /// The collection was modified after the enumerator was created.
827 /// </exception> 827 /// </exception>
828 /// <filterpriority>2</filterpriority> 828 /// <filterpriority>2</filterpriority>
829 public void Reset() 829 public void Reset()
830 { 830 {
831 if( m_version != m_generation.m_cache.m_version ) 831 if( m_version != m_generation.m_cache.m_version )
832 throw new InvalidOperationException(); 832 throw new InvalidOperationException();
833 833
834 m_currentIndex = 0; 834 m_currentIndex = 0;
835 } 835 }
836 836
837 #endregion 837 #endregion
838 } 838 }
839 839
840 #endregion 840 #endregion
841 841
842 #region IGeneration Members 842 #region IGeneration Members
843 843
844 /// <summary> 844 /// <summary>
845 /// Gets or sets a value indicating whether generation was accessed since last time check. 845 /// Gets or sets a value indicating whether generation was accessed since last time check.
846 /// </summary> 846 /// </summary>
847 public bool AccessedSinceLastTimeCheck 847 public bool AccessedSinceLastTimeCheck
848 { 848 {
849 get { return m_accessedSinceLastTimeCheck; } 849 get { return m_accessedSinceLastTimeCheck; }
850 850
851 set { m_accessedSinceLastTimeCheck = value; } 851 set { m_accessedSinceLastTimeCheck = value; }
852 } 852 }
853 853
854 /// <summary> 854 /// <summary>
855 /// Gets element count in generation. 855 /// Gets element count in generation.
856 /// </summary> 856 /// </summary>
857 public int Count 857 public int Count
858 { 858 {
859 get { return m_nextUnusedElement - m_freeCount; } 859 get { return m_nextUnusedElement - m_freeCount; }
860 } 860 }
861 861
862 /// <summary> 862 /// <summary>
863 /// Gets or sets generation's expiration time. 863 /// Gets or sets generation's expiration time.
864 /// </summary> 864 /// </summary>
865 public DateTime ExpirationTime 865 public DateTime ExpirationTime
866 { 866 {
867 get { return m_expirationTime1; } 867 get { return m_expirationTime1; }
868 868
869 set { m_expirationTime1 = value; } 869 set { m_expirationTime1 = value; }
870 } 870 }
871 871
872 /// <summary> 872 /// <summary>
873 /// Gets or sets size of data stored to generation. 873 /// Gets or sets size of data stored to generation.
874 /// </summary> 874 /// </summary>
875 public long Size 875 public long Size
876 { 876 {
877 get { return m_size; } 877 get { return m_size; }
878 878
879 private set { m_size = value; } 879 private set { m_size = value; }
880 } 880 }
881 881
882 /// <summary> 882 /// <summary>
883 /// Clear all elements from the generation and make generation new again. 883 /// Clear all elements from the generation and make generation new again.
884 /// </summary> 884 /// </summary>
885 /// <remarks> 885 /// <remarks>
886 /// When generation is new, it is allowed to add new elements to it and 886 /// When generation is new, it is allowed to add new elements to it and
887 /// <see cref="IGeneration.TryGetValue"/>doesn't remove elements from it. 887 /// <see cref="IGeneration.TryGetValue"/>doesn't remove elements from it.
888 /// </remarks> 888 /// </remarks>
889 /// <seealso cref="IGeneration.MakeOld"/> 889 /// <seealso cref="IGeneration.MakeOld"/>
890 public void Clear() 890 public void Clear()
891 { 891 {
892 for( int i = m_buckets.Length - 1 ; i >= 0 ; i-- ) 892 for( int i = m_buckets.Length - 1 ; i >= 0 ; i-- )
893 { 893 {
894 m_buckets[ i ] = -1; 894 m_buckets[ i ] = -1;
895 } 895 }
896 896
897 Array.Clear( m_elements, 0, m_elements.Length ); 897 Array.Clear( m_elements, 0, m_elements.Length );
898 Size = 0; 898 Size = 0;
899 m_firstFreeElement = -1; 899 m_firstFreeElement = -1;
900 m_freeCount = 0; 900 m_freeCount = 0;
901 m_nextUnusedElement = 0; 901 m_nextUnusedElement = 0;
902 m_newGeneration = true; 902 m_newGeneration = true;
903 ExpirationTime = DateTime.MaxValue; 903 ExpirationTime = DateTime.MaxValue;
904 } 904 }
905 905
906 /// <summary> 906 /// <summary>
907 /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key. 907 /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key.
908 /// </summary> 908 /// </summary>
909 /// <param name="bucketIndex"> 909 /// <param name="bucketIndex">
910 /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>. 910 /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>.
911 /// </param> 911 /// </param>
912 /// <param name="key"> 912 /// <param name="key">
913 /// The key to locate in the <see cref="IGeneration"/>. 913 /// The key to locate in the <see cref="IGeneration"/>.
914 /// </param> 914 /// </param>
915 /// <returns> 915 /// <returns>
916 /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>; 916 /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>;
917 /// otherwise <see langword="false"/>. 917 /// otherwise <see langword="false"/>.
918 /// </returns> 918 /// </returns>
919 public bool Contains( int bucketIndex, TKey key ) 919 public bool Contains( int bucketIndex, TKey key )
920 { 920 {
921 int previousIndex; 921 int previousIndex;
922 if( FindElementIndex( bucketIndex, key, true, out previousIndex ) == -1 ) 922 if( FindElementIndex( bucketIndex, key, true, out previousIndex ) == -1 )
923 return false; 923 return false;
924 924
925 AccessedSinceLastTimeCheck = true; 925 AccessedSinceLastTimeCheck = true;
926 return true; 926 return true;
927 } 927 }
928 928
929 /// <summary> 929 /// <summary>
930 /// Returns an enumerator that iterates through the elements stored <see cref="HashGeneration"/>. 930 /// Returns an enumerator that iterates through the elements stored <see cref="HashGeneration"/>.
931 /// </summary> 931 /// </summary>
932 /// <returns> 932 /// <returns>
933 /// A <see cref="IEnumerator"/> that can be used to iterate through the <see cref="HashGeneration"/>. 933 /// A <see cref="IEnumerator"/> that can be used to iterate through the <see cref="HashGeneration"/>.
934 /// </returns> 934 /// </returns>
935 /// <filterpriority>1</filterpriority> 935 /// <filterpriority>1</filterpriority>
936 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 936 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
937 { 937 {
938 return new Enumerator( this ); 938 return new Enumerator( this );
939 } 939 }
940 940
941 /// <summary> 941 /// <summary>
942 /// Make from generation old generation. 942 /// Make from generation old generation.
943 /// </summary> 943 /// </summary>
944 /// <remarks> 944 /// <remarks>
945 /// When generation is old, <see cref="IGeneration.TryGetValue"/> hit removes element from the generation. 945 /// When generation is old, <see cref="IGeneration.TryGetValue"/> hit removes element from the generation.
946 /// </remarks> 946 /// </remarks>
947 /// <seealso cref="IGeneration.Clear"/> 947 /// <seealso cref="IGeneration.Clear"/>
948 public void MakeOld() 948 public void MakeOld()
949 { 949 {
950 m_newGeneration = false; 950 m_newGeneration = false;
951 } 951 }
952 952
953 /// <summary> 953 /// <summary>
954 /// Remove element associated with the key from the generation. 954 /// Remove element associated with the key from the generation.
955 /// </summary> 955 /// </summary>
956 /// <param name="bucketIndex"> 956 /// <param name="bucketIndex">
957 /// The element's bucket index. 957 /// The element's bucket index.
958 /// </param> 958 /// </param>
959 /// <param name="key"> 959 /// <param name="key">
960 /// The element's key. 960 /// The element's key.
961 /// </param> 961 /// </param>
962 /// <returns> 962 /// <returns>
963 /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>. 963 /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>.
964 /// </returns> 964 /// </returns>
965 public bool Remove( int bucketIndex, TKey key ) 965 public bool Remove( int bucketIndex, TKey key )
966 { 966 {
967 int previousIndex; 967 int previousIndex;
968 int entryIndex = FindElementIndex( bucketIndex, key, false, out previousIndex ); 968 int entryIndex = FindElementIndex( bucketIndex, key, false, out previousIndex );
969 if( entryIndex != -1 ) 969 if( entryIndex != -1 )
970 { 970 {
971 RemoveElement( bucketIndex, entryIndex, previousIndex ); 971 RemoveElement( bucketIndex, entryIndex, previousIndex );
972 AccessedSinceLastTimeCheck = true; 972 AccessedSinceLastTimeCheck = true;
973 return true; 973 return true;
974 } 974 }
975 975
976 return false; 976 return false;
977 } 977 }
978 978
979 /// <summary> 979 /// <summary>
980 /// Set or add element to generation. 980 /// Set or add element to generation.
981 /// </summary> 981 /// </summary>
982 /// <param name="bucketIndex"> 982 /// <param name="bucketIndex">
983 /// The element's bucket index. 983 /// The element's bucket index.
984 /// </param> 984 /// </param>
985 /// <param name="key"> 985 /// <param name="key">
986 /// The element's key. 986 /// The element's key.
987 /// </param> 987 /// </param>
988 /// <param name="value"> 988 /// <param name="value">
989 /// The element's value. 989 /// The element's value.
990 /// </param> 990 /// </param>
991 /// <param name="size"> 991 /// <param name="size">
992 /// The element's size. 992 /// The element's size.
993 /// </param> 993 /// </param>
994 /// <returns> 994 /// <returns>
995 /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>. 995 /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>.
996 /// </returns> 996 /// </returns>
997 /// <remarks> 997 /// <remarks>
998 /// <para> 998 /// <para>
999 /// If element was already existing in generation and new element size fits to collection limits, 999 /// If element was already existing in generation and new element size fits to collection limits,
1000 /// then it's value is replaced with new one and size information is updated. If element didn't 1000 /// then it's value is replaced with new one and size information is updated. If element didn't
1001 /// exists in generation before, then generation must have empty space for a new element and 1001 /// exists in generation before, then generation must have empty space for a new element and
1002 /// size must fit generation's limits, before element is added to generation. 1002 /// size must fit generation's limits, before element is added to generation.
1003 /// </para> 1003 /// </para>
1004 /// </remarks> 1004 /// </remarks>
1005 public bool Set( int bucketIndex, TKey key, TValue value, long size ) 1005 public bool Set( int bucketIndex, TKey key, TValue value, long size )
1006 { 1006 {
1007 Debug.Assert( m_newGeneration, "It is possible to insert new elements only to newest generation." ); 1007 Debug.Assert( m_newGeneration, "It is possible to insert new elements only to newest generation." );
1008 Debug.Assert( size > 0, "New element size should be more than 0." ); 1008 Debug.Assert( size > 0, "New element size should be more than 0." );
1009 1009
1010 int previousIndex; 1010 int previousIndex;
1011 int elementIndex = FindElementIndex( bucketIndex, key, true, out previousIndex ); 1011 int elementIndex = FindElementIndex( bucketIndex, key, true, out previousIndex );
1012 if( elementIndex == -1 ) 1012 if( elementIndex == -1 )
1013 { 1013 {
1014 // New key 1014 // New key
1015 if( Size + size > m_cache.m_generationMaxSize || 1015 if( Size + size > m_cache.m_generationMaxSize ||
1016 (m_nextUnusedElement == m_cache.m_generationElementCount && m_freeCount == 0) ) 1016 (m_nextUnusedElement == m_cache.m_generationElementCount && m_freeCount == 0) )
1017 { 1017 {
1018 // Generation is full 1018 // Generation is full
1019 return false; 1019 return false;
1020 } 1020 }
1021 1021
1022 // Increase size of generation 1022 // Increase size of generation
1023 Size += size; 1023 Size += size;
1024 1024
1025 // Get first free entry and update free entry list 1025 // Get first free entry and update free entry list
1026 if( m_firstFreeElement != -1 ) 1026 if( m_firstFreeElement != -1 )
1027 { 1027 {
1028 // There was entry that was removed 1028 // There was entry that was removed
1029 elementIndex = m_firstFreeElement; 1029 elementIndex = m_firstFreeElement;
1030 m_firstFreeElement = m_elements[ elementIndex ].Next; 1030 m_firstFreeElement = m_elements[ elementIndex ].Next;
1031 m_freeCount--; 1031 m_freeCount--;
1032 } 1032 }
1033 else 1033 else
1034 { 1034 {
1035 // No entries removed so far - just take a last one 1035 // No entries removed so far - just take a last one
1036 elementIndex = m_nextUnusedElement; 1036 elementIndex = m_nextUnusedElement;
1037 m_nextUnusedElement++; 1037 m_nextUnusedElement++;
1038 } 1038 }
1039 1039
1040 Debug.Assert( m_elements[ elementIndex ].IsFree, "Allocated element is not free." ); 1040 Debug.Assert( m_elements[ elementIndex ].IsFree, "Allocated element is not free." );
1041 1041
1042 // Move new entry to front 1042 // Move new entry to front
1043 m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ]; 1043 m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ];
1044 m_buckets[ bucketIndex ] = elementIndex; 1044 m_buckets[ bucketIndex ] = elementIndex;
1045 1045
1046 // Set key and update count 1046 // Set key and update count
1047 m_elements[ elementIndex ].Key = key; 1047 m_elements[ elementIndex ].Key = key;
1048 } 1048 }
1049 else 1049 else
1050 { 1050 {
1051 // Existing key 1051 // Existing key
1052 if( Size - m_elements[ elementIndex ].Size + size > m_cache.m_generationMaxSize ) 1052 if( Size - m_elements[ elementIndex ].Size + size > m_cache.m_generationMaxSize )
1053 { 1053 {
1054 // Generation is full 1054 // Generation is full
1055 // Remove existing element, because generation is going to be recycled to 1055 // Remove existing element, because generation is going to be recycled to
1056 // old generation and element is stored to new generation 1056 // old generation and element is stored to new generation
1057 RemoveElement( bucketIndex, elementIndex, previousIndex ); 1057 RemoveElement( bucketIndex, elementIndex, previousIndex );
1058 return false; 1058 return false;
1059 } 1059 }
1060 1060
1061 // Update generation's size 1061 // Update generation's size
1062 Size = Size - m_elements[ elementIndex ].Size + size; 1062 Size = Size - m_elements[ elementIndex ].Size + size;
1063 } 1063 }
1064 1064
1065 // Finally set value and size 1065 // Finally set value and size
1066 m_elements[ elementIndex ].Value = value; 1066 m_elements[ elementIndex ].Value = value;
1067 m_elements[ elementIndex ].Size = size; 1067 m_elements[ elementIndex ].Size = size;
1068 1068
1069 // Success - key was inserterted to generation 1069 // Success - key was inserterted to generation
1070 AccessedSinceLastTimeCheck = true; 1070 AccessedSinceLastTimeCheck = true;
1071 return true; 1071 return true;
1072 } 1072 }
1073 1073
1074 /// <summary> 1074 /// <summary>
1075 /// Try to get element associated with key. 1075 /// Try to get element associated with key.
1076 /// </summary> 1076 /// </summary>
1077 /// <param name="bucketIndex"> 1077 /// <param name="bucketIndex">
1078 /// The element's bucket index. 1078 /// The element's bucket index.
1079 /// </param> 1079 /// </param>
1080 /// <param name="key"> 1080 /// <param name="key">
1081 /// The element's key. 1081 /// The element's key.
1082 /// </param> 1082 /// </param>
1083 /// <param name="value"> 1083 /// <param name="value">
1084 /// The element's value. 1084 /// The element's value.
1085 /// </param> 1085 /// </param>
1086 /// <param name="size"> 1086 /// <param name="size">
1087 /// The element's size. 1087 /// The element's size.
1088 /// </param> 1088 /// </param>
1089 /// <returns> 1089 /// <returns>
1090 /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>. 1090 /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>.
1091 /// </returns> 1091 /// </returns>
1092 /// <remarks> 1092 /// <remarks>
1093 /// <para> 1093 /// <para>
1094 /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/> 1094 /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/>
1095 /// are set to default value (default(TValue) and 0). 1095 /// are set to default value (default(TValue) and 0).
1096 /// </para> 1096 /// </para>
1097 /// </remarks> 1097 /// </remarks>
1098 public bool TryGetValue( int bucketIndex, TKey key, out TValue value, out long size ) 1098 public bool TryGetValue( int bucketIndex, TKey key, out TValue value, out long size )
1099 { 1099 {
1100 // Find entry index, 1100 // Find entry index,
1101 int previousIndex; 1101 int previousIndex;
1102 int elementIndex = FindElementIndex( bucketIndex, key, m_newGeneration, out previousIndex ); 1102 int elementIndex = FindElementIndex( bucketIndex, key, m_newGeneration, out previousIndex );
1103 if( elementIndex == -1 ) 1103 if( elementIndex == -1 )
1104 { 1104 {
1105 value = default(TValue); 1105 value = default(TValue);
1106 size = 0; 1106 size = 0;
1107 return false; 1107 return false;
1108 } 1108 }
1109 1109
1110 value = m_elements[ elementIndex ].Value; 1110 value = m_elements[ elementIndex ].Value;
1111 size = m_elements[ elementIndex ].Size; 1111 size = m_elements[ elementIndex ].Size;
1112 1112
1113 if( !m_newGeneration ) 1113 if( !m_newGeneration )
1114 { 1114 {
1115 // Old generation - remove element, because it is moved to new generation 1115 // Old generation - remove element, because it is moved to new generation
1116 RemoveElement( bucketIndex, elementIndex, previousIndex ); 1116 RemoveElement( bucketIndex, elementIndex, previousIndex );
1117 } 1117 }
1118 1118
1119 AccessedSinceLastTimeCheck = true; 1119 AccessedSinceLastTimeCheck = true;
1120 return true; 1120 return true;
1121 } 1121 }
1122 1122
1123 /// <summary> 1123 /// <summary>
1124 /// Returns an enumerator that iterates through a collection. 1124 /// Returns an enumerator that iterates through a collection.
1125 /// </summary> 1125 /// </summary>
1126 /// <returns> 1126 /// <returns>
1127 /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection. 1127 /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
1128 /// </returns> 1128 /// </returns>
1129 /// <filterpriority>2</filterpriority> 1129 /// <filterpriority>2</filterpriority>
1130 IEnumerator IEnumerable.GetEnumerator() 1130 IEnumerator IEnumerable.GetEnumerator()
1131 { 1131 {
1132 return GetEnumerator(); 1132 return GetEnumerator();
1133 } 1133 }
1134 1134
1135 #endregion 1135 #endregion
1136 } 1136 }
1137 1137
1138 #endregion 1138 #endregion
1139 1139
1140 #region Nested type: IGeneration 1140 #region Nested type: IGeneration
1141 1141
1142 /// <summary> 1142 /// <summary>
1143 /// Cache element generation interface 1143 /// Cache element generation interface
1144 /// </summary> 1144 /// </summary>
1145 /// <remarks> 1145 /// <remarks>
1146 /// <para> 1146 /// <para>
1147 /// Generation can hold limited count of elements and limited size of data. 1147 /// Generation can hold limited count of elements and limited size of data.
1148 /// </para> 1148 /// </para>
1149 /// <para> 1149 /// <para>
1150 /// There are two kind generations: "new generation" and "old generation(s)". All new elements 1150 /// There are two kind generations: "new generation" and "old generation(s)". All new elements
1151 /// are added to "new generation". 1151 /// are added to "new generation".
1152 /// </para> 1152 /// </para>
1153 /// </remarks> 1153 /// </remarks>
1154 protected interface IGeneration : IEnumerable<KeyValuePair<TKey, TValue>> 1154 protected interface IGeneration : IEnumerable<KeyValuePair<TKey, TValue>>
1155 { 1155 {
1156 /// <summary> 1156 /// <summary>
1157 /// Gets or sets a value indicating whether generation was accessed since last time check. 1157 /// Gets or sets a value indicating whether generation was accessed since last time check.
1158 /// </summary> 1158 /// </summary>
1159 bool AccessedSinceLastTimeCheck { get; set; } 1159 bool AccessedSinceLastTimeCheck { get; set; }
1160 1160
1161 /// <summary> 1161 /// <summary>
1162 /// Gets element count in generation. 1162 /// Gets element count in generation.
1163 /// </summary> 1163 /// </summary>
1164 int Count { get; } 1164 int Count { get; }
1165 1165
1166 /// <summary> 1166 /// <summary>
1167 /// Gets or sets generation's expiration time. 1167 /// Gets or sets generation's expiration time.
1168 /// </summary> 1168 /// </summary>
1169 DateTime ExpirationTime { get; set; } 1169 DateTime ExpirationTime { get; set; }
1170 1170
1171 /// <summary> 1171 /// <summary>
1172 /// Gets size of data stored to generation. 1172 /// Gets size of data stored to generation.
1173 /// </summary> 1173 /// </summary>
1174 long Size { get; } 1174 long Size { get; }
1175 1175
1176 /// <summary> 1176 /// <summary>
1177 /// Clear all elements from the generation and make generation new again. 1177 /// Clear all elements from the generation and make generation new again.
1178 /// </summary> 1178 /// </summary>
1179 /// <remarks> 1179 /// <remarks>
1180 /// When generation is new, it is allowed to add new elements to it and 1180 /// When generation is new, it is allowed to add new elements to it and
1181 /// <see cref="TryGetValue"/>doesn't remove elements from it. 1181 /// <see cref="TryGetValue"/>doesn't remove elements from it.
1182 /// </remarks> 1182 /// </remarks>
1183 /// <seealso cref="MakeOld"/> 1183 /// <seealso cref="MakeOld"/>
1184 void Clear(); 1184 void Clear();
1185 1185
1186 /// <summary> 1186 /// <summary>
1187 /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key. 1187 /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key.
1188 /// </summary> 1188 /// </summary>
1189 /// <param name="bucketIndex"> 1189 /// <param name="bucketIndex">
1190 /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>. 1190 /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>.
1191 /// </param> 1191 /// </param>
1192 /// <param name="key"> 1192 /// <param name="key">
1193 /// The key to locate in the <see cref="IGeneration"/>. 1193 /// The key to locate in the <see cref="IGeneration"/>.
1194 /// </param> 1194 /// </param>
1195 /// <returns> 1195 /// <returns>
1196 /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>; 1196 /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>;
1197 /// otherwise <see langword="false"/>. 1197 /// otherwise <see langword="false"/>.
1198 /// </returns> 1198 /// </returns>
1199 bool Contains( int bucketIndex, TKey key ); 1199 bool Contains( int bucketIndex, TKey key );
1200 1200
1201 /// <summary> 1201 /// <summary>
1202 /// Make from generation old generation. 1202 /// Make from generation old generation.
1203 /// </summary> 1203 /// </summary>
1204 /// <remarks> 1204 /// <remarks>
1205 /// When generation is old, <see cref="TryGetValue"/> hit removes element from the generation. 1205 /// When generation is old, <see cref="TryGetValue"/> hit removes element from the generation.
1206 /// </remarks> 1206 /// </remarks>
1207 /// <seealso cref="Clear"/> 1207 /// <seealso cref="Clear"/>
1208 void MakeOld(); 1208 void MakeOld();
1209 1209
1210 /// <summary> 1210 /// <summary>
1211 /// Remove element associated with the key from the generation. 1211 /// Remove element associated with the key from the generation.
1212 /// </summary> 1212 /// </summary>
1213 /// <param name="bucketIndex"> 1213 /// <param name="bucketIndex">
1214 /// The element's bucket index. 1214 /// The element's bucket index.
1215 /// </param> 1215 /// </param>
1216 /// <param name="key"> 1216 /// <param name="key">
1217 /// The element's key. 1217 /// The element's key.
1218 /// </param> 1218 /// </param>
1219 /// <returns> 1219 /// <returns>
1220 /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>. 1220 /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>.
1221 /// </returns> 1221 /// </returns>
1222 bool Remove( int bucketIndex, TKey key ); 1222 bool Remove( int bucketIndex, TKey key );
1223 1223
1224 /// <summary> 1224 /// <summary>
1225 /// Set or add element to generation. 1225 /// Set or add element to generation.
1226 /// </summary> 1226 /// </summary>
1227 /// <param name="bucketIndex"> 1227 /// <param name="bucketIndex">
1228 /// The element's bucket index. 1228 /// The element's bucket index.
1229 /// </param> 1229 /// </param>
1230 /// <param name="key"> 1230 /// <param name="key">
1231 /// The element's key. 1231 /// The element's key.
1232 /// </param> 1232 /// </param>
1233 /// <param name="value"> 1233 /// <param name="value">
1234 /// The element's value. 1234 /// The element's value.
1235 /// </param> 1235 /// </param>
1236 /// <param name="size"> 1236 /// <param name="size">
1237 /// The element's size. 1237 /// The element's size.
1238 /// </param> 1238 /// </param>
1239 /// <returns> 1239 /// <returns>
1240 /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>. 1240 /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>.
1241 /// </returns> 1241 /// </returns>
1242 /// <remarks> 1242 /// <remarks>
1243 /// <para> 1243 /// <para>
1244 /// If element was already existing in generation and new element size fits to collection limits, 1244 /// If element was already existing in generation and new element size fits to collection limits,
1245 /// then it's value is replaced with new one and size information is updated. If element didn't 1245 /// then it's value is replaced with new one and size information is updated. If element didn't
1246 /// exists in generation before, then generation must have empty space for a new element and 1246 /// exists in generation before, then generation must have empty space for a new element and
1247 /// size must fit generation's limits, before element is added to generation. 1247 /// size must fit generation's limits, before element is added to generation.
1248 /// </para> 1248 /// </para>
1249 /// </remarks> 1249 /// </remarks>
1250 bool Set( int bucketIndex, TKey key, TValue value, long size ); 1250 bool Set( int bucketIndex, TKey key, TValue value, long size );
1251 1251
1252 /// <summary> 1252 /// <summary>
1253 /// Try to get element associated with key. 1253 /// Try to get element associated with key.
1254 /// </summary> 1254 /// </summary>
1255 /// <param name="bucketIndex"> 1255 /// <param name="bucketIndex">
1256 /// The element's bucket index. 1256 /// The element's bucket index.
1257 /// </param> 1257 /// </param>
1258 /// <param name="key"> 1258 /// <param name="key">
1259 /// The element's key. 1259 /// The element's key.
1260 /// </param> 1260 /// </param>
1261 /// <param name="value"> 1261 /// <param name="value">
1262 /// The element's value. 1262 /// The element's value.
1263 /// </param> 1263 /// </param>
1264 /// <param name="size"> 1264 /// <param name="size">
1265 /// The element's size. 1265 /// The element's size.
1266 /// </param> 1266 /// </param>
1267 /// <returns> 1267 /// <returns>
1268 /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>. 1268 /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>.
1269 /// </returns> 1269 /// </returns>
1270 /// <remarks> 1270 /// <remarks>
1271 /// <para> 1271 /// <para>
1272 /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/> 1272 /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/>
1273 /// are set to default value (default(TValue) and 0). 1273 /// are set to default value (default(TValue) and 0).
1274 /// </para> 1274 /// </para>
1275 /// </remarks> 1275 /// </remarks>
1276 bool TryGetValue( int bucketIndex, TKey key, out TValue value, out long size ); 1276 bool TryGetValue( int bucketIndex, TKey key, out TValue value, out long size );
1277 } 1277 }
1278 1278
1279 #endregion 1279 #endregion
1280 1280
1281 #region ICnmCache<TKey,TValue> Members 1281 #region ICnmCache<TKey,TValue> Members
1282 1282
1283 /// <summary> 1283 /// <summary>
1284 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 1284 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
1285 /// </summary> 1285 /// </summary>
1286 /// <remarks> 1286 /// <remarks>
1287 /// <para> 1287 /// <para>
1288 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 1288 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
1289 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1289 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1290 /// </para> 1290 /// </para>
1291 /// </remarks> 1291 /// </remarks>
1292 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 1292 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
1293 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1293 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1294 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1294 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1295 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 1295 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
1296 public int Count 1296 public int Count
1297 { 1297 {
1298 get { return m_newGeneration.Count + m_oldGeneration.Count; } 1298 get { return m_newGeneration.Count + m_oldGeneration.Count; }
1299 } 1299 }
1300 1300
1301 /// <summary> 1301 /// <summary>
1302 /// Gets or sets elements expiration time. 1302 /// Gets or sets elements expiration time.
1303 /// </summary> 1303 /// </summary>
1304 /// <value> 1304 /// <value>
1305 /// Elements expiration time. 1305 /// Elements expiration time.
1306 /// </value> 1306 /// </value>
1307 /// <remarks> 1307 /// <remarks>
1308 /// <para> 1308 /// <para>
1309 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 1309 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
1310 /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is 1310 /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is
1311 /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the 1311 /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the
1312 /// <see cref="ICnmCache{TKey,TValue}"/>. 1312 /// <see cref="ICnmCache{TKey,TValue}"/>.
1313 /// </para> 1313 /// </para>
1314 /// <para> 1314 /// <para>
1315 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time, 1315 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
1316 /// because total size or count of elements stored to cache is larger than <see cref="ICnmCache{TKey,TValue}.MaxSize"/> or <see cref="ICnmCache{TKey,TValue}.MaxCount"/>. 1316 /// because total size or count of elements stored to cache is larger than <see cref="ICnmCache{TKey,TValue}.MaxSize"/> or <see cref="ICnmCache{TKey,TValue}.MaxCount"/>.
1317 /// </para> 1317 /// </para>
1318 /// <para> 1318 /// <para>
1319 /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>. 1319 /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
1320 /// </para> 1320 /// </para>
1321 /// <para> 1321 /// <para>
1322 /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired. 1322 /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired.
1323 /// </para> 1323 /// </para>
1324 /// <para> 1324 /// <para>
1325 /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>. 1325 /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
1326 /// </para> 1326 /// </para>
1327 /// </remarks> 1327 /// </remarks>
1328 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 1328 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
1329 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1329 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1330 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1330 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1331 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1331 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1332 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/> 1332 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
1333 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 1333 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
1334 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 1334 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
1335 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 1335 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
1336 public TimeSpan ExpirationTime 1336 public TimeSpan ExpirationTime
1337 { 1337 {
1338 get { return m_expirationTime; } 1338 get { return m_expirationTime; }
1339 1339
1340 set 1340 set
1341 { 1341 {
1342 if( value < MinExpirationTime ) 1342 if( value < MinExpirationTime )
1343 value = MinExpirationTime; 1343 value = MinExpirationTime;
1344 1344
1345 if( m_expirationTime == value ) 1345 if( m_expirationTime == value )
1346 return; 1346 return;
1347 1347
1348 m_newGeneration.ExpirationTime = (m_newGeneration.ExpirationTime - m_expirationTime) + value; 1348 m_newGeneration.ExpirationTime = (m_newGeneration.ExpirationTime - m_expirationTime) + value;
1349 m_oldGeneration.ExpirationTime = (m_oldGeneration.ExpirationTime - m_expirationTime) + value; 1349 m_oldGeneration.ExpirationTime = (m_oldGeneration.ExpirationTime - m_expirationTime) + value;
1350 m_expirationTime = value; 1350 m_expirationTime = value;
1351 1351
1352 PurgeExpired(); 1352 PurgeExpired();
1353 } 1353 }
1354 } 1354 }
1355 1355
1356 /// <summary> 1356 /// <summary>
1357 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements. 1357 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
1358 /// </summary> 1358 /// </summary>
1359 /// <value> 1359 /// <value>
1360 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited; 1360 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
1361 /// otherwise, <see langword="false"/>. 1361 /// otherwise, <see langword="false"/>.
1362 /// </value> 1362 /// </value>
1363 /// <remarks> 1363 /// <remarks>
1364 /// <para> 1364 /// <para>
1365 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 1365 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
1366 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1366 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1367 /// </para> 1367 /// </para>
1368 /// </remarks> 1368 /// </remarks>
1369 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/> 1369 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
1370 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 1370 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
1371 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1371 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1372 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 1372 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
1373 public bool IsCountLimited 1373 public bool IsCountLimited
1374 { 1374 {
1375 get { return true; } 1375 get { return true; }
1376 } 1376 }
1377 1377
1378 /// <summary> 1378 /// <summary>
1379 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements. 1379 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
1380 /// </summary> 1380 /// </summary>
1381 /// <value> 1381 /// <value>
1382 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited; 1382 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
1383 /// otherwise, <see langword="false"/>. 1383 /// otherwise, <see langword="false"/>.
1384 /// </value> 1384 /// </value>
1385 /// <remarks> 1385 /// <remarks>
1386 /// <para> 1386 /// <para>
1387 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 1387 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
1388 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1388 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1389 /// </para> 1389 /// </para>
1390 /// </remarks> 1390 /// </remarks>
1391 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 1391 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
1392 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 1392 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
1393 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 1393 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
1394 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1394 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1395 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 1395 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
1396 public bool IsSizeLimited 1396 public bool IsSizeLimited
1397 { 1397 {
1398 get { return true; } 1398 get { return true; }
1399 } 1399 }
1400 1400
1401 /// <summary> 1401 /// <summary>
1402 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe). 1402 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
1403 /// </summary> 1403 /// </summary>
1404 /// <value> 1404 /// <value>
1405 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe); 1405 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
1406 /// otherwise, <see langword="false"/>. 1406 /// otherwise, <see langword="false"/>.
1407 /// </value> 1407 /// </value>
1408 /// <remarks> 1408 /// <remarks>
1409 /// <para> 1409 /// <para>
1410 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use 1410 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
1411 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class 1411 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
1412 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object. 1412 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
1413 /// </para> 1413 /// </para>
1414 /// </remarks> 1414 /// </remarks>
1415 /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/> 1415 /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/>
1416 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 1416 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
1417 public bool IsSynchronized 1417 public bool IsSynchronized
1418 { 1418 {
1419 get { return false; } 1419 get { return false; }
1420 } 1420 }
1421 1421
1422 /// <summary> 1422 /// <summary>
1423 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time. 1423 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
1424 /// </summary> 1424 /// </summary>
1425 /// <value> 1425 /// <value>
1426 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements; 1426 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
1427 /// otherwise, <see langword="false"/>. 1427 /// otherwise, <see langword="false"/>.
1428 /// </value> 1428 /// </value>
1429 /// <remarks> 1429 /// <remarks>
1430 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/> 1430 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/>
1431 /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from 1431 /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from
1432 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may 1432 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
1433 /// stay longer in cache. 1433 /// stay longer in cache.
1434 /// </remarks> 1434 /// </remarks>
1435 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 1435 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
1436 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1436 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1437 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1437 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1438 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1438 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1439 public bool IsTimeLimited 1439 public bool IsTimeLimited
1440 { 1440 {
1441 get { return ExpirationTime != TimeSpan.MaxValue; } 1441 get { return ExpirationTime != TimeSpan.MaxValue; }
1442 } 1442 }
1443 1443
1444 /// <summary> 1444 /// <summary>
1445 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>. 1445 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
1446 /// </summary> 1446 /// </summary>
1447 /// <value> 1447 /// <value>
1448 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements; 1448 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
1449 /// otherwise maximal allowed count of elements. 1449 /// otherwise maximal allowed count of elements.
1450 /// </value> 1450 /// </value>
1451 /// <remarks> 1451 /// <remarks>
1452 /// <para> 1452 /// <para>
1453 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 1453 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
1454 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1454 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1455 /// </para> 1455 /// </para>
1456 /// </remarks> 1456 /// </remarks>
1457 public int MaxCount 1457 public int MaxCount
1458 { 1458 {
1459 get { return m_maxCount; } 1459 get { return m_maxCount; }
1460 1460
1461 set 1461 set
1462 { 1462 {
1463 if( value < 8 ) 1463 if( value < 8 )
1464 value = 8; 1464 value = 8;
1465 if( m_maxCount == value ) 1465 if( m_maxCount == value )
1466 return; 1466 return;
1467 1467
1468 m_maxCount = value; 1468 m_maxCount = value;
1469 Initialize(); 1469 Initialize();
1470 } 1470 }
1471 } 1471 }
1472 1472
1473 /// <summary> 1473 /// <summary>
1474 /// <para>Gets maximal allowed element size.</para> 1474 /// <para>Gets maximal allowed element size.</para>
1475 /// </summary> 1475 /// </summary>
1476 /// <value> 1476 /// <value>
1477 /// Maximal allowed element size. 1477 /// Maximal allowed element size.
1478 /// </value> 1478 /// </value>
1479 /// <remarks> 1479 /// <remarks>
1480 /// <para> 1480 /// <para>
1481 /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is 1481 /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
1482 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>. 1482 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
1483 /// </para> 1483 /// </para>
1484 /// </remarks> 1484 /// </remarks>
1485 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1485 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1486 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1486 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1487 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 1487 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
1488 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 1488 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
1489 public long MaxElementSize 1489 public long MaxElementSize
1490 { 1490 {
1491 get { return m_maxElementSize; } 1491 get { return m_maxElementSize; }
1492 1492
1493 private set { m_maxElementSize = value; } 1493 private set { m_maxElementSize = value; }
1494 } 1494 }
1495 1495
1496 /// <summary> 1496 /// <summary>
1497 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 1497 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
1498 /// </summary> 1498 /// </summary>
1499 /// <value> 1499 /// <value>
1500 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 1500 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
1501 /// </value> 1501 /// </value>
1502 /// <remarks> 1502 /// <remarks>
1503 /// <para> 1503 /// <para>
1504 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure. 1504 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
1505 /// </para> 1505 /// </para>
1506 /// <para> 1506 /// <para>
1507 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 1507 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
1508 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1508 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1509 /// </para> 1509 /// </para>
1510 /// </remarks> 1510 /// </remarks>
1511 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 1511 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
1512 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1512 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1513 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 1513 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
1514 public long MaxSize 1514 public long MaxSize
1515 { 1515 {
1516 get { return m_maxSize; } 1516 get { return m_maxSize; }
1517 1517
1518 set 1518 set
1519 { 1519 {
1520 if( value < 8 ) 1520 if( value < 8 )
1521 value = 8; 1521 value = 8;
1522 if( m_maxSize == value ) 1522 if( m_maxSize == value )
1523 return; 1523 return;
1524 1524
1525 m_maxSize = value; 1525 m_maxSize = value;
1526 Initialize(); 1526 Initialize();
1527 } 1527 }
1528 } 1528 }
1529 1529
1530 /// <summary> 1530 /// <summary>
1531 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 1531 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
1532 /// </summary> 1532 /// </summary>
1533 /// <value> 1533 /// <value>
1534 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 1534 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
1535 /// </value> 1535 /// </value>
1536 /// <remarks> 1536 /// <remarks>
1537 /// <para> 1537 /// <para>
1538 /// Normally bytes, but can be any suitable unit of measure. 1538 /// Normally bytes, but can be any suitable unit of measure.
1539 /// </para> 1539 /// </para>
1540 /// <para> 1540 /// <para>
1541 /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method. 1541 /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method.
1542 /// </para> 1542 /// </para>
1543 /// <para> 1543 /// <para>
1544 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 1544 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
1545 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 1545 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
1546 /// </para> 1546 /// </para>
1547 /// </remarks> 1547 /// </remarks>
1548 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 1548 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
1549 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1549 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1550 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 1550 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
1551 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1551 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1552 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 1552 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
1553 public long Size 1553 public long Size
1554 { 1554 {
1555 get { return m_newGeneration.Size + m_oldGeneration.Size; } 1555 get { return m_newGeneration.Size + m_oldGeneration.Size; }
1556 } 1556 }
1557 1557
1558 /// <summary> 1558 /// <summary>
1559 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 1559 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
1560 /// </summary> 1560 /// </summary>
1561 /// <value> 1561 /// <value>
1562 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 1562 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
1563 /// </value> 1563 /// </value>
1564 /// <remarks> 1564 /// <remarks>
1565 /// <para> 1565 /// <para>
1566 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/> 1566 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
1567 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to 1567 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
1568 /// <see cref="ICnmCache{TKey,TValue}"/>. 1568 /// <see cref="ICnmCache{TKey,TValue}"/>.
1569 /// </para> 1569 /// </para>
1570 /// </remarks> 1570 /// </remarks>
1571 /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/> 1571 /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/>
1572 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 1572 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
1573 public object SyncRoot 1573 public object SyncRoot
1574 { 1574 {
1575 get { return m_syncRoot; } 1575 get { return m_syncRoot; }
1576 } 1576 }
1577 1577
1578 /// <summary> 1578 /// <summary>
1579 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>. 1579 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
1580 /// </summary> 1580 /// </summary>
1581 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1581 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1582 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 1582 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
1583 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 1583 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
1584 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 1584 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
1585 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1585 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1586 public void Clear() 1586 public void Clear()
1587 { 1587 {
1588 m_newGeneration.Clear(); 1588 m_newGeneration.Clear();
1589 m_oldGeneration.Clear(); 1589 m_oldGeneration.Clear();
1590 m_oldGeneration.MakeOld(); 1590 m_oldGeneration.MakeOld();
1591 m_version++; 1591 m_version++;
1592 } 1592 }
1593 1593
1594 /// <summary> 1594 /// <summary>
1595 /// Returns an enumerator that iterates through the elements stored to <see cref="CnmMemoryCache{TKey,TValue}"/>. 1595 /// Returns an enumerator that iterates through the elements stored to <see cref="CnmMemoryCache{TKey,TValue}"/>.
1596 /// </summary> 1596 /// </summary>
1597 /// <returns> 1597 /// <returns>
1598 /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection. 1598 /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
1599 /// </returns> 1599 /// </returns>
1600 /// <filterpriority>1</filterpriority> 1600 /// <filterpriority>1</filterpriority>
1601 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 1601 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
1602 { 1602 {
1603 return new Enumerator( this ); 1603 return new Enumerator( this );
1604 } 1604 }
1605 1605
1606 /// <summary> 1606 /// <summary>
1607 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>. 1607 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
1608 /// </summary> 1608 /// </summary>
1609 /// <remarks> 1609 /// <remarks>
1610 /// <para> 1610 /// <para>
1611 /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>. 1611 /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
1612 /// </para> 1612 /// </para>
1613 /// <para> 1613 /// <para>
1614 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements 1614 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
1615 /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache. 1615 /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache.
1616 /// </para> 1616 /// </para>
1617 /// </remarks> 1617 /// </remarks>
1618 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 1618 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
1619 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 1619 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
1620 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1620 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1621 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 1621 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
1622 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 1622 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
1623 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 1623 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
1624 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 1624 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
1625 public void PurgeExpired() 1625 public void PurgeExpired()
1626 { 1626 {
1627 m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks; 1627 m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks;
1628 1628
1629 if( !IsTimeLimited ) 1629 if( !IsTimeLimited )
1630 return; 1630 return;
1631 1631
1632 DateTime now = DateTime.Now; 1632 DateTime now = DateTime.Now;
1633 if( m_newGeneration.AccessedSinceLastTimeCheck ) 1633 if( m_newGeneration.AccessedSinceLastTimeCheck )
1634 { 1634 {
1635 // New generation has been accessed since last check 1635 // New generation has been accessed since last check
1636 // Update it's expiration time. 1636 // Update it's expiration time.
1637 m_newGeneration.ExpirationTime = now + ExpirationTime; 1637 m_newGeneration.ExpirationTime = now + ExpirationTime;
1638 m_newGeneration.AccessedSinceLastTimeCheck = false; 1638 m_newGeneration.AccessedSinceLastTimeCheck = false;
1639 } 1639 }
1640 else if( m_newGeneration.ExpirationTime < now ) 1640 else if( m_newGeneration.ExpirationTime < now )
1641 { 1641 {
1642 // New generation has been expired. 1642 // New generation has been expired.
1643 // --> also old generation must be expired. 1643 // --> also old generation must be expired.
1644 PurgeGeneration( m_newGeneration ); 1644 PurgeGeneration( m_newGeneration );
1645 PurgeGeneration( m_oldGeneration ); 1645 PurgeGeneration( m_oldGeneration );
1646 return; 1646 return;
1647 } 1647 }
1648 1648
1649 if( m_oldGeneration.ExpirationTime < now ) 1649 if( m_oldGeneration.ExpirationTime < now )
1650 PurgeGeneration( m_oldGeneration ); 1650 PurgeGeneration( m_oldGeneration );
1651 } 1651 }
1652 1652
1653 /// <summary> 1653 /// <summary>
1654 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 1654 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
1655 /// </summary> 1655 /// </summary>
1656 /// <param name="key"> 1656 /// <param name="key">
1657 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 1657 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
1658 /// </param> 1658 /// </param>
1659 /// <exception cref="ArgumentNullException"> 1659 /// <exception cref="ArgumentNullException">
1660 /// <paramref name="key"/>is <see langword="null"/>. 1660 /// <paramref name="key"/>is <see langword="null"/>.
1661 /// </exception> 1661 /// </exception>
1662 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1662 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1663 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 1663 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
1664 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 1664 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
1665 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 1665 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
1666 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1666 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1667 public void Remove( TKey key ) 1667 public void Remove( TKey key )
1668 { 1668 {
1669 if( key == null ) 1669 if( key == null )
1670 throw new ArgumentNullException( "key" ); 1670 throw new ArgumentNullException( "key" );
1671 1671
1672 int bucketIndex = GetBucketIndex( key ); 1672 int bucketIndex = GetBucketIndex( key );
1673 if( !m_newGeneration.Remove( bucketIndex, key ) ) 1673 if( !m_newGeneration.Remove( bucketIndex, key ) )
1674 { 1674 {
1675 if( !m_oldGeneration.Remove( bucketIndex, key ) ) 1675 if( !m_oldGeneration.Remove( bucketIndex, key ) )
1676 { 1676 {
1677 CheckExpired(); 1677 CheckExpired();
1678 return; 1678 return;
1679 } 1679 }
1680 } 1680 }
1681 1681
1682 CheckExpired(); 1682 CheckExpired();
1683 m_version++; 1683 m_version++;
1684 } 1684 }
1685 1685
1686 /// <summary> 1686 /// <summary>
1687 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 1687 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
1688 /// </summary> 1688 /// </summary>
1689 /// <param name="keys"> 1689 /// <param name="keys">
1690 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 1690 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
1691 /// </param> 1691 /// </param>
1692 /// <exception cref="ArgumentNullException"> 1692 /// <exception cref="ArgumentNullException">
1693 /// <paramref name="keys"/>is <see langword="null"/>. 1693 /// <paramref name="keys"/>is <see langword="null"/>.
1694 /// </exception> 1694 /// </exception>
1695 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1695 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1696 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 1696 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
1697 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 1697 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
1698 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 1698 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
1699 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1699 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1700 public void RemoveRange( IEnumerable<TKey> keys ) 1700 public void RemoveRange( IEnumerable<TKey> keys )
1701 { 1701 {
1702 if( keys == null ) 1702 if( keys == null )
1703 throw new ArgumentNullException( "keys" ); 1703 throw new ArgumentNullException( "keys" );
1704 1704
1705 foreach( TKey key in keys ) 1705 foreach( TKey key in keys )
1706 { 1706 {
1707 if( key == null ) 1707 if( key == null )
1708 continue; 1708 continue;
1709 1709
1710 int bucketIndex = GetBucketIndex( key ); 1710 int bucketIndex = GetBucketIndex( key );
1711 if( !m_newGeneration.Remove( bucketIndex, key ) ) 1711 if( !m_newGeneration.Remove( bucketIndex, key ) )
1712 m_oldGeneration.Remove( bucketIndex, key ); 1712 m_oldGeneration.Remove( bucketIndex, key );
1713 } 1713 }
1714 1714
1715 CheckExpired(); 1715 CheckExpired();
1716 m_version++; 1716 m_version++;
1717 } 1717 }
1718 1718
1719 /// <summary> 1719 /// <summary>
1720 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to 1720 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
1721 /// <see cref="ICnmCache{TKey,TValue}"/>. 1721 /// <see cref="ICnmCache{TKey,TValue}"/>.
1722 /// </summary> 1722 /// </summary>
1723 /// <param name="key"> 1723 /// <param name="key">
1724 /// The object used as the key of the element. Can't be <see langword="null"/> reference. 1724 /// The object used as the key of the element. Can't be <see langword="null"/> reference.
1725 /// </param> 1725 /// </param>
1726 /// <param name="value"> 1726 /// <param name="value">
1727 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed. 1727 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
1728 /// </param> 1728 /// </param>
1729 /// <param name="size"> 1729 /// <param name="size">
1730 /// The element's size. Normally bytes, but can be any suitable unit of measure. 1730 /// The element's size. Normally bytes, but can be any suitable unit of measure.
1731 /// </param> 1731 /// </param>
1732 /// <returns> 1732 /// <returns>
1733 /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>; 1733 /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
1734 /// otherwise <see langword="false"/>. 1734 /// otherwise <see langword="false"/>.
1735 /// </returns> 1735 /// </returns>
1736 /// <exception cref="ArgumentNullException"> 1736 /// <exception cref="ArgumentNullException">
1737 /// <paramref name="key"/>is <see langword="null"/>. 1737 /// <paramref name="key"/>is <see langword="null"/>.
1738 /// </exception> 1738 /// </exception>
1739 /// <exception cref="ArgumentOutOfRangeException"> 1739 /// <exception cref="ArgumentOutOfRangeException">
1740 /// The element's <paramref name="size"/> is less than 0. 1740 /// The element's <paramref name="size"/> is less than 0.
1741 /// </exception> 1741 /// </exception>
1742 /// <remarks> 1742 /// <remarks>
1743 /// <para> 1743 /// <para>
1744 /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is 1744 /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
1745 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is 1745 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
1746 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>. 1746 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
1747 /// </para> 1747 /// </para>
1748 /// <para> 1748 /// <para>
1749 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 1749 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
1750 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 1750 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
1751 /// </para> 1751 /// </para>
1752 /// <para> 1752 /// <para>
1753 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 1753 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
1754 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 1754 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
1755 /// </para> 1755 /// </para>
1756 /// </remarks> 1756 /// </remarks>
1757 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 1757 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
1758 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 1758 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
1759 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 1759 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
1760 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 1760 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
1761 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 1761 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
1762 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 1762 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
1763 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1763 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1764 public bool Set( TKey key, TValue value, long size ) 1764 public bool Set( TKey key, TValue value, long size )
1765 { 1765 {
1766 if( key == null ) 1766 if( key == null )
1767 throw new ArgumentNullException( "key" ); 1767 throw new ArgumentNullException( "key" );
1768 1768
1769 if( size < 0 ) 1769 if( size < 0 )
1770 throw new ArgumentOutOfRangeException( "size", size, "Value's size can't be less than 0." ); 1770 throw new ArgumentOutOfRangeException( "size", size, "Value's size can't be less than 0." );
1771 1771
1772 if( size > MaxElementSize ) 1772 if( size > MaxElementSize )
1773 { 1773 {
1774 // Entry size is too big to fit cache - ignore it 1774 // Entry size is too big to fit cache - ignore it
1775 Remove( key ); 1775 Remove( key );
1776 return false; 1776 return false;
1777 } 1777 }
1778 1778
1779 if( size == 0 ) 1779 if( size == 0 )
1780 size = 1; 1780 size = 1;
1781 1781
1782 int bucketIndex = GetBucketIndex( key ); 1782 int bucketIndex = GetBucketIndex( key );
1783 m_oldGeneration.Remove( bucketIndex, key ); 1783 m_oldGeneration.Remove( bucketIndex, key );
1784 AddToNewGeneration( bucketIndex, key, value, size ); 1784 AddToNewGeneration( bucketIndex, key, value, size );
1785 CheckExpired(); 1785 CheckExpired();
1786 1786
1787 return true; 1787 return true;
1788 } 1788 }
1789 1789
1790 /// <summary> 1790 /// <summary>
1791 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>. 1791 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
1792 /// </summary> 1792 /// </summary>
1793 /// <returns> 1793 /// <returns>
1794 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with 1794 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
1795 /// the specified key; otherwise, <see langword="false"/>. 1795 /// the specified key; otherwise, <see langword="false"/>.
1796 /// </returns> 1796 /// </returns>
1797 /// <param name="key"> 1797 /// <param name="key">
1798 /// The key whose <paramref name="value"/> to get. 1798 /// The key whose <paramref name="value"/> to get.
1799 /// </param> 1799 /// </param>
1800 /// <param name="value"> 1800 /// <param name="value">
1801 /// When this method returns, the value associated with the specified <paramref name="key"/>, 1801 /// When this method returns, the value associated with the specified <paramref name="key"/>,
1802 /// if the <paramref name="key"/> is found; otherwise, the 1802 /// if the <paramref name="key"/> is found; otherwise, the
1803 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized. 1803 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
1804 /// </param> 1804 /// </param>
1805 /// <exception cref="ArgumentNullException"> 1805 /// <exception cref="ArgumentNullException">
1806 /// <paramref name="key"/>is <see langword="null"/>. 1806 /// <paramref name="key"/>is <see langword="null"/>.
1807 /// </exception> 1807 /// </exception>
1808 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 1808 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
1809 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 1809 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
1810 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 1810 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
1811 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 1811 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
1812 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 1812 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
1813 public bool TryGetValue( TKey key, out TValue value ) 1813 public bool TryGetValue( TKey key, out TValue value )
1814 { 1814 {
1815 if( key == null ) 1815 if( key == null )
1816 throw new ArgumentNullException( "key" ); 1816 throw new ArgumentNullException( "key" );
1817 1817
1818 int bucketIndex = GetBucketIndex( key ); 1818 int bucketIndex = GetBucketIndex( key );
1819 long size; 1819 long size;
1820 if( m_newGeneration.TryGetValue( bucketIndex, key, out value, out size ) ) 1820 if( m_newGeneration.TryGetValue( bucketIndex, key, out value, out size ) )
1821 { 1821 {
1822 CheckExpired(); 1822 CheckExpired();
1823 return true; 1823 return true;
1824 } 1824 }
1825 1825
1826 if( m_oldGeneration.TryGetValue( bucketIndex, key, out value, out size ) ) 1826 if( m_oldGeneration.TryGetValue( bucketIndex, key, out value, out size ) )
1827 { 1827 {
1828 // Move element to new generation 1828 // Move element to new generation
1829 AddToNewGeneration( bucketIndex, key, value, size ); 1829 AddToNewGeneration( bucketIndex, key, value, size );
1830 CheckExpired(); 1830 CheckExpired();
1831 return true; 1831 return true;
1832 } 1832 }
1833 1833
1834 CheckExpired(); 1834 CheckExpired();
1835 return false; 1835 return false;
1836 } 1836 }
1837 1837
1838 /// <summary> 1838 /// <summary>
1839 /// Returns an enumerator that iterates through a collection. 1839 /// Returns an enumerator that iterates through a collection.
1840 /// </summary> 1840 /// </summary>
1841 /// <returns> 1841 /// <returns>
1842 /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection. 1842 /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
1843 /// </returns> 1843 /// </returns>
1844 /// <filterpriority>2</filterpriority> 1844 /// <filterpriority>2</filterpriority>
1845 IEnumerator IEnumerable.GetEnumerator() 1845 IEnumerator IEnumerable.GetEnumerator()
1846 { 1846 {
1847 return GetEnumerator(); 1847 return GetEnumerator();
1848 } 1848 }
1849 1849
1850 #endregion 1850 #endregion
1851 } 1851 }
1852} 1852}
diff --git a/OpenSim/Framework/CnmSynchronizedCache.cs b/OpenSim/Framework/CnmSynchronizedCache.cs
index 418a095..bf588ce 100644
--- a/OpenSim/Framework/CnmSynchronizedCache.cs
+++ b/OpenSim/Framework/CnmSynchronizedCache.cs
@@ -1,746 +1,746 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections; 28using System.Collections;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading; 30using System.Threading;
31 31
32namespace OpenSim.Framework 32namespace OpenSim.Framework
33{ 33{
34 /// <summary> 34 /// <summary>
35 /// Synchronized Cenome cache wrapper. 35 /// Synchronized Cenome cache wrapper.
36 /// </summary> 36 /// </summary>
37 /// <typeparam name="TKey"> 37 /// <typeparam name="TKey">
38 /// The type of keys in the cache. 38 /// The type of keys in the cache.
39 /// </typeparam> 39 /// </typeparam>
40 /// <typeparam name="TValue"> 40 /// <typeparam name="TValue">
41 /// The type of values in the cache. 41 /// The type of values in the cache.
42 /// </typeparam> 42 /// </typeparam>
43 /// <remarks> 43 /// <remarks>
44 /// <para> 44 /// <para>
45 /// Enumerator will block other threads, until enumerator's <see cref="IDisposable.Dispose"/> method is called. 45 /// Enumerator will block other threads, until enumerator's <see cref="IDisposable.Dispose"/> method is called.
46 /// "foreach" statement is automatically calling it. 46 /// "foreach" statement is automatically calling it.
47 /// </para> 47 /// </para>
48 /// </remarks> 48 /// </remarks>
49 public class CnmSynchronizedCache<TKey, TValue> : ICnmCache<TKey, TValue> 49 public class CnmSynchronizedCache<TKey, TValue> : ICnmCache<TKey, TValue>
50 { 50 {
51 /// <summary> 51 /// <summary>
52 /// The cache object. 52 /// The cache object.
53 /// </summary> 53 /// </summary>
54 private readonly ICnmCache<TKey, TValue> m_cache; 54 private readonly ICnmCache<TKey, TValue> m_cache;
55 55
56 /// <summary> 56 /// <summary>
57 /// Synchronization root. 57 /// Synchronization root.
58 /// </summary> 58 /// </summary>
59 private readonly object m_syncRoot; 59 private readonly object m_syncRoot;
60 60
61 /// <summary> 61 /// <summary>
62 /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class. 62 /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class.
63 /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class. 63 /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class.
64 /// </summary> 64 /// </summary>
65 /// <param name="cache"> 65 /// <param name="cache">
66 /// The cache. 66 /// The cache.
67 /// </param> 67 /// </param>
68 private CnmSynchronizedCache( ICnmCache<TKey, TValue> cache ) 68 private CnmSynchronizedCache( ICnmCache<TKey, TValue> cache )
69 { 69 {
70 m_cache = cache; 70 m_cache = cache;
71 m_syncRoot = m_cache.SyncRoot; 71 m_syncRoot = m_cache.SyncRoot;
72 } 72 }
73 73
74 /// <summary> 74 /// <summary>
75 /// Returns a <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe). 75 /// Returns a <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe).
76 /// </summary> 76 /// </summary>
77 /// <param name="cache"> 77 /// <param name="cache">
78 /// The <see cref="ICnmCache{TKey,TValue}"/> to synchronize. 78 /// The <see cref="ICnmCache{TKey,TValue}"/> to synchronize.
79 /// </param> 79 /// </param>
80 /// <returns> 80 /// <returns>
81 /// A <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe). 81 /// A <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe).
82 /// </returns> 82 /// </returns>
83 /// <exception cref="ArgumentNullException"> 83 /// <exception cref="ArgumentNullException">
84 /// <paramref name="cache"/>is null. 84 /// <paramref name="cache"/>is null.
85 /// </exception> 85 /// </exception>
86 public static ICnmCache<TKey, TValue> Synchronized( ICnmCache<TKey, TValue> cache ) 86 public static ICnmCache<TKey, TValue> Synchronized( ICnmCache<TKey, TValue> cache )
87 { 87 {
88 if( cache == null ) 88 if( cache == null )
89 throw new ArgumentNullException( "cache" ); 89 throw new ArgumentNullException( "cache" );
90 return cache.IsSynchronized ? cache : new CnmSynchronizedCache<TKey, TValue>( cache ); 90 return cache.IsSynchronized ? cache : new CnmSynchronizedCache<TKey, TValue>( cache );
91 } 91 }
92 92
93 #region Nested type: SynchronizedEnumerator 93 #region Nested type: SynchronizedEnumerator
94 94
95 /// <summary> 95 /// <summary>
96 /// Synchronized enumerator. 96 /// Synchronized enumerator.
97 /// </summary> 97 /// </summary>
98 private class SynchronizedEnumerator : IEnumerator<KeyValuePair<TKey, TValue>> 98 private class SynchronizedEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>
99 { 99 {
100 /// <summary> 100 /// <summary>
101 /// Enumerator that is being synchronized. 101 /// Enumerator that is being synchronized.
102 /// </summary> 102 /// </summary>
103 private readonly IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator; 103 private readonly IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator;
104 104
105 /// <summary> 105 /// <summary>
106 /// Synchronization root. 106 /// Synchronization root.
107 /// </summary> 107 /// </summary>
108 private object m_syncRoot; 108 private object m_syncRoot;
109 109
110 /// <summary> 110 /// <summary>
111 /// Initializes a new instance of the <see cref="SynchronizedEnumerator"/> class. 111 /// Initializes a new instance of the <see cref="SynchronizedEnumerator"/> class.
112 /// </summary> 112 /// </summary>
113 /// <param name="enumerator"> 113 /// <param name="enumerator">
114 /// The enumerator that is being synchronized. 114 /// The enumerator that is being synchronized.
115 /// </param> 115 /// </param>
116 /// <param name="syncRoot"> 116 /// <param name="syncRoot">
117 /// The sync root. 117 /// The sync root.
118 /// </param> 118 /// </param>
119 public SynchronizedEnumerator( IEnumerator<KeyValuePair<TKey, TValue>> enumerator, object syncRoot ) 119 public SynchronizedEnumerator( IEnumerator<KeyValuePair<TKey, TValue>> enumerator, object syncRoot )
120 { 120 {
121 m_syncRoot = syncRoot; 121 m_syncRoot = syncRoot;
122 m_enumerator = enumerator; 122 m_enumerator = enumerator;
123 Monitor.Enter( m_syncRoot ); 123 Monitor.Enter( m_syncRoot );
124 } 124 }
125 125
126 /// <summary> 126 /// <summary>
127 /// Finalizes an instance of the <see cref="SynchronizedEnumerator"/> class. 127 /// Finalizes an instance of the <see cref="SynchronizedEnumerator"/> class.
128 /// </summary> 128 /// </summary>
129 ~SynchronizedEnumerator() 129 ~SynchronizedEnumerator()
130 { 130 {
131 Dispose(); 131 Dispose();
132 } 132 }
133 133
134 #region IEnumerator<KeyValuePair<TKey,TValue>> Members 134 #region IEnumerator<KeyValuePair<TKey,TValue>> Members
135 135
136 /// <summary> 136 /// <summary>
137 /// Gets the element in the collection at the current position of the enumerator. 137 /// Gets the element in the collection at the current position of the enumerator.
138 /// </summary> 138 /// </summary>
139 /// <returns> 139 /// <returns>
140 /// The element in the collection at the current position of the enumerator. 140 /// The element in the collection at the current position of the enumerator.
141 /// </returns> 141 /// </returns>
142 /// <exception cref="InvalidOperationException"> 142 /// <exception cref="InvalidOperationException">
143 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called. 143 /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
144 /// </exception> 144 /// </exception>
145 public KeyValuePair<TKey, TValue> Current 145 public KeyValuePair<TKey, TValue> Current
146 { 146 {
147 get { return m_enumerator.Current; } 147 get { return m_enumerator.Current; }
148 } 148 }
149 149
150 /// <summary> 150 /// <summary>
151 /// Gets the current element in the collection. 151 /// Gets the current element in the collection.
152 /// </summary> 152 /// </summary>
153 /// <returns> 153 /// <returns>
154 /// The current element in the collection. 154 /// The current element in the collection.
155 /// </returns> 155 /// </returns>
156 /// <exception cref="InvalidOperationException"> 156 /// <exception cref="InvalidOperationException">
157 /// The enumerator is positioned before the first element of the collection or after the last element. 157 /// The enumerator is positioned before the first element of the collection or after the last element.
158 /// </exception><filterpriority>2</filterpriority> 158 /// </exception><filterpriority>2</filterpriority>
159 object IEnumerator.Current 159 object IEnumerator.Current
160 { 160 {
161 get { return Current; } 161 get { return Current; }
162 } 162 }
163 163
164 /// <summary> 164 /// <summary>
165 /// Releases synchronization lock. 165 /// Releases synchronization lock.
166 /// </summary> 166 /// </summary>
167 public void Dispose() 167 public void Dispose()
168 { 168 {
169 if( m_syncRoot != null ) 169 if( m_syncRoot != null )
170 { 170 {
171 Monitor.Exit( m_syncRoot ); 171 Monitor.Exit( m_syncRoot );
172 m_syncRoot = null; 172 m_syncRoot = null;
173 } 173 }
174 174
175 m_enumerator.Dispose(); 175 m_enumerator.Dispose();
176 GC.SuppressFinalize( this ); 176 GC.SuppressFinalize( this );
177 } 177 }
178 178
179 /// <summary> 179 /// <summary>
180 /// Advances the enumerator to the next element of the collection. 180 /// Advances the enumerator to the next element of the collection.
181 /// </summary> 181 /// </summary>
182 /// <returns> 182 /// <returns>
183 /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection. 183 /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
184 /// </returns> 184 /// </returns>
185 /// <exception cref="InvalidOperationException"> 185 /// <exception cref="InvalidOperationException">
186 /// The collection was modified after the enumerator was created. 186 /// The collection was modified after the enumerator was created.
187 /// </exception> 187 /// </exception>
188 public bool MoveNext() 188 public bool MoveNext()
189 { 189 {
190 return m_enumerator.MoveNext(); 190 return m_enumerator.MoveNext();
191 } 191 }
192 192
193 /// <summary> 193 /// <summary>
194 /// Sets the enumerator to its initial position, which is before the first element in the collection. 194 /// Sets the enumerator to its initial position, which is before the first element in the collection.
195 /// </summary> 195 /// </summary>
196 /// <exception cref="InvalidOperationException"> 196 /// <exception cref="InvalidOperationException">
197 /// The collection was modified after the enumerator was created. 197 /// The collection was modified after the enumerator was created.
198 /// </exception> 198 /// </exception>
199 public void Reset() 199 public void Reset()
200 { 200 {
201 m_enumerator.Reset(); 201 m_enumerator.Reset();
202 } 202 }
203 203
204 #endregion 204 #endregion
205 } 205 }
206 206
207 #endregion 207 #endregion
208 208
209 #region ICnmCache<TKey,TValue> Members 209 #region ICnmCache<TKey,TValue> Members
210 210
211 /// <summary> 211 /// <summary>
212 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 212 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
213 /// </summary> 213 /// </summary>
214 /// <remarks> 214 /// <remarks>
215 /// <para> 215 /// <para>
216 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 216 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
217 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 217 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
218 /// </para> 218 /// </para>
219 /// </remarks> 219 /// </remarks>
220 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 220 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
221 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 221 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
222 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 222 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
223 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 223 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
224 public int Count 224 public int Count
225 { 225 {
226 get 226 get
227 { 227 {
228 lock( m_syncRoot ) 228 lock( m_syncRoot )
229 { 229 {
230 return m_cache.Count; 230 return m_cache.Count;
231 } 231 }
232 } 232 }
233 } 233 }
234 234
235 /// <summary> 235 /// <summary>
236 /// Gets or sets elements expiration time. 236 /// Gets or sets elements expiration time.
237 /// </summary> 237 /// </summary>
238 /// <value> 238 /// <value>
239 /// Elements expiration time. 239 /// Elements expiration time.
240 /// </value> 240 /// </value>
241 /// <remarks> 241 /// <remarks>
242 /// <para> 242 /// <para>
243 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 243 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
244 /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is 244 /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is
245 /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the 245 /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the
246 /// <see cref="ICnmCache{TKey,TValue}"/>. 246 /// <see cref="ICnmCache{TKey,TValue}"/>.
247 /// </para> 247 /// </para>
248 /// <para> 248 /// <para>
249 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time, 249 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
250 /// because total size or count of elements stored to cache is larger than <see cref="ICnmCache{TKey,TValue}.MaxSize"/> or <see cref="ICnmCache{TKey,TValue}.MaxCount"/>. 250 /// because total size or count of elements stored to cache is larger than <see cref="ICnmCache{TKey,TValue}.MaxSize"/> or <see cref="ICnmCache{TKey,TValue}.MaxCount"/>.
251 /// </para> 251 /// </para>
252 /// <para> 252 /// <para>
253 /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>. 253 /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
254 /// </para> 254 /// </para>
255 /// <para> 255 /// <para>
256 /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired. 256 /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired.
257 /// </para> 257 /// </para>
258 /// <para> 258 /// <para>
259 /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>. 259 /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
260 /// </para> 260 /// </para>
261 /// </remarks> 261 /// </remarks>
262 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 262 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
263 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 263 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
264 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 264 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
265 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 265 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
266 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/> 266 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
267 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 267 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
268 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 268 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
269 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 269 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
270 public TimeSpan ExpirationTime 270 public TimeSpan ExpirationTime
271 { 271 {
272 get 272 get
273 { 273 {
274 lock( m_syncRoot ) 274 lock( m_syncRoot )
275 { 275 {
276 return m_cache.ExpirationTime; 276 return m_cache.ExpirationTime;
277 } 277 }
278 } 278 }
279 279
280 set 280 set
281 { 281 {
282 lock( m_syncRoot ) 282 lock( m_syncRoot )
283 { 283 {
284 m_cache.ExpirationTime = value; 284 m_cache.ExpirationTime = value;
285 } 285 }
286 } 286 }
287 } 287 }
288 288
289 /// <summary> 289 /// <summary>
290 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements. 290 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
291 /// </summary> 291 /// </summary>
292 /// <value> 292 /// <value>
293 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited; 293 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
294 /// otherwise, <see langword="false"/>. 294 /// otherwise, <see langword="false"/>.
295 /// </value> 295 /// </value>
296 /// <remarks> 296 /// <remarks>
297 /// <para> 297 /// <para>
298 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 298 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
299 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 299 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
300 /// </para> 300 /// </para>
301 /// </remarks> 301 /// </remarks>
302 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/> 302 /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
303 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/> 303 /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
304 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 304 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
305 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 305 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
306 public bool IsCountLimited 306 public bool IsCountLimited
307 { 307 {
308 get 308 get
309 { 309 {
310 lock( m_syncRoot ) 310 lock( m_syncRoot )
311 { 311 {
312 return m_cache.IsCountLimited; 312 return m_cache.IsCountLimited;
313 } 313 }
314 } 314 }
315 } 315 }
316 316
317 /// <summary> 317 /// <summary>
318 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements. 318 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
319 /// </summary> 319 /// </summary>
320 /// <value> 320 /// <value>
321 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited; 321 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
322 /// otherwise, <see langword="false"/>. 322 /// otherwise, <see langword="false"/>.
323 /// </value> 323 /// </value>
324 /// <remarks> 324 /// <remarks>
325 /// <para> 325 /// <para>
326 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 326 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
327 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 327 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
328 /// </para> 328 /// </para>
329 /// </remarks> 329 /// </remarks>
330 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 330 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
331 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 331 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
332 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 332 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
333 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 333 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
334 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 334 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
335 public bool IsSizeLimited 335 public bool IsSizeLimited
336 { 336 {
337 get 337 get
338 { 338 {
339 lock( m_syncRoot ) 339 lock( m_syncRoot )
340 { 340 {
341 return m_cache.IsSizeLimited; 341 return m_cache.IsSizeLimited;
342 } 342 }
343 } 343 }
344 } 344 }
345 345
346 /// <summary> 346 /// <summary>
347 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe). 347 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
348 /// </summary> 348 /// </summary>
349 /// <value> 349 /// <value>
350 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe); 350 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
351 /// otherwise, <see langword="false"/>. 351 /// otherwise, <see langword="false"/>.
352 /// </value> 352 /// </value>
353 /// <remarks> 353 /// <remarks>
354 /// <para> 354 /// <para>
355 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use 355 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
356 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class 356 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
357 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object. 357 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
358 /// </para> 358 /// </para>
359 /// </remarks> 359 /// </remarks>
360 /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/> 360 /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/>
361 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 361 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
362 public bool IsSynchronized 362 public bool IsSynchronized
363 { 363 {
364 get { return true; } 364 get { return true; }
365 } 365 }
366 366
367 /// <summary> 367 /// <summary>
368 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time. 368 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
369 /// </summary> 369 /// </summary>
370 /// <value> 370 /// <value>
371 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements; 371 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
372 /// otherwise, <see langword="false"/>. 372 /// otherwise, <see langword="false"/>.
373 /// </value> 373 /// </value>
374 /// <remarks> 374 /// <remarks>
375 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/> 375 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/>
376 /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from 376 /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from
377 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may 377 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
378 /// stay longer in cache. 378 /// stay longer in cache.
379 /// </remarks> 379 /// </remarks>
380 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 380 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
381 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 381 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
382 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 382 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
383 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 383 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
384 public bool IsTimeLimited 384 public bool IsTimeLimited
385 { 385 {
386 get 386 get
387 { 387 {
388 lock( m_syncRoot ) 388 lock( m_syncRoot )
389 { 389 {
390 return m_cache.IsTimeLimited; 390 return m_cache.IsTimeLimited;
391 } 391 }
392 } 392 }
393 } 393 }
394 394
395 /// <summary> 395 /// <summary>
396 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>. 396 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
397 /// </summary> 397 /// </summary>
398 /// <value> 398 /// <value>
399 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements; 399 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
400 /// otherwise maximal allowed count of elements. 400 /// otherwise maximal allowed count of elements.
401 /// </value> 401 /// </value>
402 /// <remarks> 402 /// <remarks>
403 /// <para> 403 /// <para>
404 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 404 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
405 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 405 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
406 /// </para> 406 /// </para>
407 /// </remarks> 407 /// </remarks>
408 public int MaxCount 408 public int MaxCount
409 { 409 {
410 get 410 get
411 { 411 {
412 lock( m_syncRoot ) 412 lock( m_syncRoot )
413 { 413 {
414 return m_cache.MaxCount; 414 return m_cache.MaxCount;
415 } 415 }
416 } 416 }
417 417
418 set 418 set
419 { 419 {
420 lock( m_syncRoot ) 420 lock( m_syncRoot )
421 { 421 {
422 m_cache.MaxCount = value; 422 m_cache.MaxCount = value;
423 } 423 }
424 } 424 }
425 } 425 }
426 426
427 /// <summary> 427 /// <summary>
428 /// <para>Gets maximal allowed element size.</para> 428 /// <para>Gets maximal allowed element size.</para>
429 /// </summary> 429 /// </summary>
430 /// <value> 430 /// <value>
431 /// Maximal allowed element size. 431 /// Maximal allowed element size.
432 /// </value> 432 /// </value>
433 /// <remarks> 433 /// <remarks>
434 /// <para> 434 /// <para>
435 /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is 435 /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
436 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>. 436 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
437 /// </para> 437 /// </para>
438 /// </remarks> 438 /// </remarks>
439 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 439 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
440 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 440 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
441 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 441 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
442 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 442 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
443 public long MaxElementSize 443 public long MaxElementSize
444 { 444 {
445 get 445 get
446 { 446 {
447 lock( m_syncRoot ) 447 lock( m_syncRoot )
448 { 448 {
449 return m_cache.MaxElementSize; 449 return m_cache.MaxElementSize;
450 } 450 }
451 } 451 }
452 } 452 }
453 453
454 /// <summary> 454 /// <summary>
455 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 455 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
456 /// </summary> 456 /// </summary>
457 /// <value> 457 /// <value>
458 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 458 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
459 /// </value> 459 /// </value>
460 /// <remarks> 460 /// <remarks>
461 /// <para> 461 /// <para>
462 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure. 462 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
463 /// </para> 463 /// </para>
464 /// <para> 464 /// <para>
465 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 465 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
466 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 466 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
467 /// </para> 467 /// </para>
468 /// </remarks> 468 /// </remarks>
469 /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception> 469 /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception>
470 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 470 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
471 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 471 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
472 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/> 472 /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
473 public long MaxSize 473 public long MaxSize
474 { 474 {
475 get 475 get
476 { 476 {
477 lock( m_syncRoot ) 477 lock( m_syncRoot )
478 { 478 {
479 return m_cache.MaxSize; 479 return m_cache.MaxSize;
480 } 480 }
481 } 481 }
482 482
483 set 483 set
484 { 484 {
485 lock( m_syncRoot ) 485 lock( m_syncRoot )
486 { 486 {
487 m_cache.MaxSize = value; 487 m_cache.MaxSize = value;
488 } 488 }
489 } 489 }
490 } 490 }
491 491
492 /// <summary> 492 /// <summary>
493 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 493 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
494 /// </summary> 494 /// </summary>
495 /// <value> 495 /// <value>
496 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 496 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
497 /// </value> 497 /// </value>
498 /// <remarks> 498 /// <remarks>
499 /// <para> 499 /// <para>
500 /// Normally bytes, but can be any suitable unit of measure. 500 /// Normally bytes, but can be any suitable unit of measure.
501 /// </para> 501 /// </para>
502 /// <para> 502 /// <para>
503 /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method. 503 /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method.
504 /// </para> 504 /// </para>
505 /// <para> 505 /// <para>
506 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 506 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
507 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 507 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
508 /// </para> 508 /// </para>
509 /// </remarks> 509 /// </remarks>
510 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/> 510 /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
511 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 511 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
512 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/> 512 /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
513 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 513 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
514 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 514 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
515 public long Size 515 public long Size
516 { 516 {
517 get 517 get
518 { 518 {
519 lock( m_syncRoot ) 519 lock( m_syncRoot )
520 { 520 {
521 return m_cache.Size; 521 return m_cache.Size;
522 } 522 }
523 } 523 }
524 } 524 }
525 525
526 /// <summary> 526 /// <summary>
527 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 527 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
528 /// </summary> 528 /// </summary>
529 /// <value> 529 /// <value>
530 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 530 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
531 /// </value> 531 /// </value>
532 /// <remarks> 532 /// <remarks>
533 /// <para> 533 /// <para>
534 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/> 534 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
535 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to 535 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
536 /// <see cref="ICnmCache{TKey,TValue}"/>. 536 /// <see cref="ICnmCache{TKey,TValue}"/>.
537 /// </para> 537 /// </para>
538 /// </remarks> 538 /// </remarks>
539 /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/> 539 /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/>
540 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 540 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
541 public object SyncRoot 541 public object SyncRoot
542 { 542 {
543 get { return m_syncRoot; } 543 get { return m_syncRoot; }
544 } 544 }
545 545
546 /// <summary> 546 /// <summary>
547 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>. 547 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
548 /// </summary> 548 /// </summary>
549 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 549 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
550 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 550 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
551 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 551 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
552 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 552 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
553 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 553 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
554 public void Clear() 554 public void Clear()
555 { 555 {
556 lock( m_syncRoot ) 556 lock( m_syncRoot )
557 { 557 {
558 m_cache.Clear(); 558 m_cache.Clear();
559 } 559 }
560 } 560 }
561 561
562 /// <summary> 562 /// <summary>
563 /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 563 /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
564 /// </summary> 564 /// </summary>
565 /// <returns> 565 /// <returns>
566 /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection. 566 /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
567 /// </returns> 567 /// </returns>
568 /// <filterpriority>1</filterpriority> 568 /// <filterpriority>1</filterpriority>
569 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 569 public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
570 { 570 {
571 lock( m_syncRoot ) 571 lock( m_syncRoot )
572 { 572 {
573 return new SynchronizedEnumerator( m_cache.GetEnumerator(), m_syncRoot ); 573 return new SynchronizedEnumerator( m_cache.GetEnumerator(), m_syncRoot );
574 } 574 }
575 } 575 }
576 576
577 /// <summary> 577 /// <summary>
578 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>. 578 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
579 /// </summary> 579 /// </summary>
580 /// <remarks> 580 /// <remarks>
581 /// <para> 581 /// <para>
582 /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>. 582 /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
583 /// </para> 583 /// </para>
584 /// <para> 584 /// <para>
585 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements 585 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
586 /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache. 586 /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache.
587 /// </para> 587 /// </para>
588 /// </remarks> 588 /// </remarks>
589 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/> 589 /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
590 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/> 590 /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
591 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 591 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
592 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 592 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
593 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 593 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
594 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 594 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
595 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 595 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
596 public void PurgeExpired() 596 public void PurgeExpired()
597 { 597 {
598 lock( m_syncRoot ) 598 lock( m_syncRoot )
599 { 599 {
600 m_cache.PurgeExpired(); 600 m_cache.PurgeExpired();
601 } 601 }
602 } 602 }
603 603
604 /// <summary> 604 /// <summary>
605 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 605 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
606 /// </summary> 606 /// </summary>
607 /// <param name="key"> 607 /// <param name="key">
608 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 608 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
609 /// </param> 609 /// </param>
610 /// <exception cref="ArgumentNullException"> 610 /// <exception cref="ArgumentNullException">
611 /// <paramref name="key"/>is <see langword="null"/>. 611 /// <paramref name="key"/>is <see langword="null"/>.
612 /// </exception> 612 /// </exception>
613 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 613 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
614 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 614 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
615 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 615 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
616 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 616 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
617 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 617 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
618 public void Remove( TKey key ) 618 public void Remove( TKey key )
619 { 619 {
620 lock( m_syncRoot ) 620 lock( m_syncRoot )
621 { 621 {
622 m_cache.Remove( key ); 622 m_cache.Remove( key );
623 } 623 }
624 } 624 }
625 625
626 /// <summary> 626 /// <summary>
627 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 627 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
628 /// </summary> 628 /// </summary>
629 /// <param name="keys"> 629 /// <param name="keys">
630 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 630 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
631 /// </param> 631 /// </param>
632 /// <exception cref="ArgumentNullException"> 632 /// <exception cref="ArgumentNullException">
633 /// <paramref name="keys"/>is <see langword="null"/>. 633 /// <paramref name="keys"/>is <see langword="null"/>.
634 /// </exception> 634 /// </exception>
635 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 635 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
636 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 636 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
637 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 637 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
638 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 638 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
639 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 639 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
640 public void RemoveRange( IEnumerable<TKey> keys ) 640 public void RemoveRange( IEnumerable<TKey> keys )
641 { 641 {
642 lock( m_syncRoot ) 642 lock( m_syncRoot )
643 { 643 {
644 m_cache.RemoveRange( keys ); 644 m_cache.RemoveRange( keys );
645 } 645 }
646 } 646 }
647 647
648 /// <summary> 648 /// <summary>
649 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to 649 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
650 /// <see cref="ICnmCache{TKey,TValue}"/>. 650 /// <see cref="ICnmCache{TKey,TValue}"/>.
651 /// </summary> 651 /// </summary>
652 /// <param name="key"> 652 /// <param name="key">
653 /// The object used as the key of the element. Can't be <see langword="null"/> reference. 653 /// The object used as the key of the element. Can't be <see langword="null"/> reference.
654 /// </param> 654 /// </param>
655 /// <param name="value"> 655 /// <param name="value">
656 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed. 656 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
657 /// </param> 657 /// </param>
658 /// <param name="size"> 658 /// <param name="size">
659 /// The element's size. Normally bytes, but can be any suitable unit of measure. 659 /// The element's size. Normally bytes, but can be any suitable unit of measure.
660 /// </param> 660 /// </param>
661 /// <returns> 661 /// <returns>
662 /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>; 662 /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
663 /// otherwise <see langword="false"/>. 663 /// otherwise <see langword="false"/>.
664 /// </returns> 664 /// </returns>
665 /// <exception cref="ArgumentNullException"> 665 /// <exception cref="ArgumentNullException">
666 /// <paramref name="key"/>is <see langword="null"/>. 666 /// <paramref name="key"/>is <see langword="null"/>.
667 /// </exception> 667 /// </exception>
668 /// <exception cref="ArgumentOutOfRangeException"> 668 /// <exception cref="ArgumentOutOfRangeException">
669 /// The element's <paramref name="size"/> is less than 0. 669 /// The element's <paramref name="size"/> is less than 0.
670 /// </exception> 670 /// </exception>
671 /// <remarks> 671 /// <remarks>
672 /// <para> 672 /// <para>
673 /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is 673 /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
674 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is 674 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
675 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>. 675 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
676 /// </para> 676 /// </para>
677 /// <para> 677 /// <para>
678 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 678 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
679 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 679 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
680 /// </para> 680 /// </para>
681 /// <para> 681 /// <para>
682 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 682 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
683 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 683 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
684 /// </para> 684 /// </para>
685 /// </remarks> 685 /// </remarks>
686 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/> 686 /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
687 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/> 687 /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
688 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 688 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
689 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 689 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
690 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/> 690 /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
691 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 691 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
692 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 692 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
693 public bool Set( TKey key, TValue value, long size ) 693 public bool Set( TKey key, TValue value, long size )
694 { 694 {
695 lock( m_syncRoot ) 695 lock( m_syncRoot )
696 { 696 {
697 return m_cache.Set( key, value, size ); 697 return m_cache.Set( key, value, size );
698 } 698 }
699 } 699 }
700 700
701 /// <summary> 701 /// <summary>
702 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>. 702 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
703 /// </summary> 703 /// </summary>
704 /// <returns> 704 /// <returns>
705 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with 705 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
706 /// the specified key; otherwise, <see langword="false"/>. 706 /// the specified key; otherwise, <see langword="false"/>.
707 /// </returns> 707 /// </returns>
708 /// <param name="key"> 708 /// <param name="key">
709 /// The key whose <paramref name="value"/> to get. 709 /// The key whose <paramref name="value"/> to get.
710 /// </param> 710 /// </param>
711 /// <param name="value"> 711 /// <param name="value">
712 /// When this method returns, the value associated with the specified <paramref name="key"/>, 712 /// When this method returns, the value associated with the specified <paramref name="key"/>,
713 /// if the <paramref name="key"/> is found; otherwise, the 713 /// if the <paramref name="key"/> is found; otherwise, the
714 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized. 714 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
715 /// </param> 715 /// </param>
716 /// <exception cref="ArgumentNullException"> 716 /// <exception cref="ArgumentNullException">
717 /// <paramref name="key"/>is <see langword="null"/>. 717 /// <paramref name="key"/>is <see langword="null"/>.
718 /// </exception> 718 /// </exception>
719 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/> 719 /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
720 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/> 720 /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
721 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/> 721 /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
722 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/> 722 /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
723 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/> 723 /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
724 public bool TryGetValue( TKey key, out TValue value ) 724 public bool TryGetValue( TKey key, out TValue value )
725 { 725 {
726 lock( m_syncRoot ) 726 lock( m_syncRoot )
727 { 727 {
728 return m_cache.TryGetValue( key, out value ); 728 return m_cache.TryGetValue( key, out value );
729 } 729 }
730 } 730 }
731 731
732 /// <summary> 732 /// <summary>
733 /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 733 /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
734 /// </summary> 734 /// </summary>
735 /// <returns> 735 /// <returns>
736 /// A <see cref="IEnumerator"/> that can be used to iterate through the collection. 736 /// A <see cref="IEnumerator"/> that can be used to iterate through the collection.
737 /// </returns> 737 /// </returns>
738 /// <filterpriority>1</filterpriority> 738 /// <filterpriority>1</filterpriority>
739 IEnumerator IEnumerable.GetEnumerator() 739 IEnumerator IEnumerable.GetEnumerator()
740 { 740 {
741 return GetEnumerator(); 741 return GetEnumerator();
742 } 742 }
743 743
744 #endregion 744 #endregion
745 } 745 }
746} 746}
diff --git a/OpenSim/Framework/ICnmCache.cs b/OpenSim/Framework/ICnmCache.cs
index cba8a7f..2f62189 100644
--- a/OpenSim/Framework/ICnmCache.cs
+++ b/OpenSim/Framework/ICnmCache.cs
@@ -1,441 +1,441 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Framework 31namespace OpenSim.Framework
32{ 32{
33 /// <summary> 33 /// <summary>
34 /// Represent generic cache to store key/value pairs (elements) limited by time, size and count of elements. 34 /// Represent generic cache to store key/value pairs (elements) limited by time, size and count of elements.
35 /// </summary> 35 /// </summary>
36 /// <typeparam name="TKey"> 36 /// <typeparam name="TKey">
37 /// The type of keys in the cache. 37 /// The type of keys in the cache.
38 /// </typeparam> 38 /// </typeparam>
39 /// <typeparam name="TValue"> 39 /// <typeparam name="TValue">
40 /// The type of values in the cache. 40 /// The type of values in the cache.
41 /// </typeparam> 41 /// </typeparam>
42 /// <remarks> 42 /// <remarks>
43 /// <para> 43 /// <para>
44 /// Cache store limitations: 44 /// Cache store limitations:
45 /// </para> 45 /// </para>
46 /// <list type="table"> 46 /// <list type="table">
47 /// <listheader> 47 /// <listheader>
48 /// <term>Limitation</term> 48 /// <term>Limitation</term>
49 /// <description>Description</description> 49 /// <description>Description</description>
50 /// </listheader> 50 /// </listheader>
51 /// <item> 51 /// <item>
52 /// <term>Time</term> 52 /// <term>Time</term>
53 /// <description> 53 /// <description>
54 /// Element that is not accessed through <see cref="TryGetValue"/> or <see cref="Set"/> in last <see cref="ExpirationTime"/> are 54 /// Element that is not accessed through <see cref="TryGetValue"/> or <see cref="Set"/> in last <see cref="ExpirationTime"/> are
55 /// removed from the cache automatically. Depending on implementation of the cache some of elements may stay longer in cache. 55 /// removed from the cache automatically. Depending on implementation of the cache some of elements may stay longer in cache.
56 /// <see cref="IsTimeLimited"/> returns <see langword="true"/>, if cache is limited by time. 56 /// <see cref="IsTimeLimited"/> returns <see langword="true"/>, if cache is limited by time.
57 /// </description> 57 /// </description>
58 /// </item> 58 /// </item>
59 /// <item> 59 /// <item>
60 /// <term>Count</term> 60 /// <term>Count</term>
61 /// <description> 61 /// <description>
62 /// When adding an new element to cache that already have <see cref="MaxCount"/> of elements, cache will remove less recently 62 /// When adding an new element to cache that already have <see cref="MaxCount"/> of elements, cache will remove less recently
63 /// used element(s) from the cache, until element fits to cache. 63 /// used element(s) from the cache, until element fits to cache.
64 /// <see cref="IsCountLimited"/> returns <see langword="true"/>, if cache is limiting element count. 64 /// <see cref="IsCountLimited"/> returns <see langword="true"/>, if cache is limiting element count.
65 /// </description> 65 /// </description>
66 /// </item> 66 /// </item>
67 /// <item> 67 /// <item>
68 /// <term>Size</term> 68 /// <term>Size</term>
69 /// <description> 69 /// <description>
70 /// <description> 70 /// <description>
71 /// When adding an new element to cache that already have <see cref="MaxSize"/> of elements, cache will remove less recently 71 /// When adding an new element to cache that already have <see cref="MaxSize"/> of elements, cache will remove less recently
72 /// used element(s) from the cache, until element fits to cache. 72 /// used element(s) from the cache, until element fits to cache.
73 /// <see cref="IsSizeLimited"/> returns <see langword="true"/>, if cache is limiting total size of elements. 73 /// <see cref="IsSizeLimited"/> returns <see langword="true"/>, if cache is limiting total size of elements.
74 /// Normally size is bytes used by element in the cache. But it can be any other suitable unit of measure. 74 /// Normally size is bytes used by element in the cache. But it can be any other suitable unit of measure.
75 /// </description> 75 /// </description>
76 /// </description> 76 /// </description>
77 /// </item> 77 /// </item>
78 /// </list> 78 /// </list>
79 /// </remarks> 79 /// </remarks>
80 public interface ICnmCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 80 public interface ICnmCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
81 { 81 {
82 /// <summary> 82 /// <summary>
83 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 83 /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
84 /// </summary> 84 /// </summary>
85 /// <remarks> 85 /// <remarks>
86 /// <para> 86 /// <para>
87 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 87 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
88 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 88 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
89 /// </para> 89 /// </para>
90 /// </remarks> 90 /// </remarks>
91 /// <seealso cref="MaxCount"/> 91 /// <seealso cref="MaxCount"/>
92 /// <seealso cref="IsCountLimited"/> 92 /// <seealso cref="IsCountLimited"/>
93 /// <seealso cref="IsSizeLimited"/> 93 /// <seealso cref="IsSizeLimited"/>
94 /// <seealso cref="IsTimeLimited"/> 94 /// <seealso cref="IsTimeLimited"/>
95 int Count { get; } 95 int Count { get; }
96 96
97 /// <summary> 97 /// <summary>
98 /// Gets or sets elements expiration time. 98 /// Gets or sets elements expiration time.
99 /// </summary> 99 /// </summary>
100 /// <value> 100 /// <value>
101 /// Elements expiration time. 101 /// Elements expiration time.
102 /// </value> 102 /// </value>
103 /// <remarks> 103 /// <remarks>
104 /// <para> 104 /// <para>
105 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ExpirationTime"/> 105 /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ExpirationTime"/>
106 /// and it is not accessed through <see cref="TryGetValue"/> method or element's value is 106 /// and it is not accessed through <see cref="TryGetValue"/> method or element's value is
107 /// not replaced by <see cref="Set"/> method, then it is automatically removed from the 107 /// not replaced by <see cref="Set"/> method, then it is automatically removed from the
108 /// <see cref="ICnmCache{TKey,TValue}"/>. 108 /// <see cref="ICnmCache{TKey,TValue}"/>.
109 /// </para> 109 /// </para>
110 /// <para> 110 /// <para>
111 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time, 111 /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
112 /// because total size or count of elements stored to cache is larger than <see cref="MaxSize"/> or <see cref="MaxCount"/>. 112 /// because total size or count of elements stored to cache is larger than <see cref="MaxSize"/> or <see cref="MaxCount"/>.
113 /// </para> 113 /// </para>
114 /// <para> 114 /// <para>
115 /// It is also possible that element stays in cache longer than <see cref="ExpirationTime"/>. 115 /// It is also possible that element stays in cache longer than <see cref="ExpirationTime"/>.
116 /// </para> 116 /// </para>
117 /// <para> 117 /// <para>
118 /// Calling <see cref="PurgeExpired"/> try to remove all elements that are expired. 118 /// Calling <see cref="PurgeExpired"/> try to remove all elements that are expired.
119 /// </para> 119 /// </para>
120 /// <para> 120 /// <para>
121 /// To disable time limit in cache, set <see cref="ExpirationTime"/> to <see cref="DateTime.MaxValue"/>. 121 /// To disable time limit in cache, set <see cref="ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
122 /// </para> 122 /// </para>
123 /// </remarks> 123 /// </remarks>
124 /// <seealso cref="IsTimeLimited"/> 124 /// <seealso cref="IsTimeLimited"/>
125 /// <seealso cref="IsCountLimited"/> 125 /// <seealso cref="IsCountLimited"/>
126 /// <seealso cref="IsSizeLimited"/> 126 /// <seealso cref="IsSizeLimited"/>
127 /// <seealso cref="PurgeExpired"/> 127 /// <seealso cref="PurgeExpired"/>
128 /// <seealso cref="Count"/> 128 /// <seealso cref="Count"/>
129 /// <seealso cref="MaxCount"/> 129 /// <seealso cref="MaxCount"/>
130 /// <seealso cref="MaxSize"/> 130 /// <seealso cref="MaxSize"/>
131 /// <seealso cref="Size"/> 131 /// <seealso cref="Size"/>
132 TimeSpan ExpirationTime { get; set; } 132 TimeSpan ExpirationTime { get; set; }
133 133
134 /// <summary> 134 /// <summary>
135 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe). 135 /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
136 /// </summary> 136 /// </summary>
137 /// <value> 137 /// <value>
138 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe); 138 /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
139 /// otherwise, <see langword="false"/>. 139 /// otherwise, <see langword="false"/>.
140 /// </value> 140 /// </value>
141 /// <remarks> 141 /// <remarks>
142 /// <para> 142 /// <para>
143 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use 143 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
144 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class 144 /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
145 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object. 145 /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
146 /// </para> 146 /// </para>
147 /// </remarks> 147 /// </remarks>
148 /// <seealso cref="SyncRoot"/> 148 /// <seealso cref="SyncRoot"/>
149 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 149 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
150 bool IsSynchronized { get; } 150 bool IsSynchronized { get; }
151 151
152 /// <summary> 152 /// <summary>
153 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements. 153 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
154 /// </summary> 154 /// </summary>
155 /// <value> 155 /// <value>
156 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited; 156 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
157 /// otherwise, <see langword="false"/>. 157 /// otherwise, <see langword="false"/>.
158 /// </value> 158 /// </value>
159 /// <remarks> 159 /// <remarks>
160 /// <para> 160 /// <para>
161 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 161 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
162 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 162 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
163 /// </para> 163 /// </para>
164 /// </remarks> 164 /// </remarks>
165 /// <seealso cref="Count"/> 165 /// <seealso cref="Count"/>
166 /// <seealso cref="MaxCount"/> 166 /// <seealso cref="MaxCount"/>
167 /// <seealso cref="IsSizeLimited"/> 167 /// <seealso cref="IsSizeLimited"/>
168 /// <seealso cref="IsTimeLimited"/> 168 /// <seealso cref="IsTimeLimited"/>
169 bool IsCountLimited { get; } 169 bool IsCountLimited { get; }
170 170
171 /// <summary> 171 /// <summary>
172 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements. 172 /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
173 /// </summary> 173 /// </summary>
174 /// <value> 174 /// <value>
175 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited; 175 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
176 /// otherwise, <see langword="false"/>. 176 /// otherwise, <see langword="false"/>.
177 /// </value> 177 /// </value>
178 /// <remarks> 178 /// <remarks>
179 /// <para> 179 /// <para>
180 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 180 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
181 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 181 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
182 /// </para> 182 /// </para>
183 /// </remarks> 183 /// </remarks>
184 /// <seealso cref="MaxElementSize"/> 184 /// <seealso cref="MaxElementSize"/>
185 /// <seealso cref="Size"/> 185 /// <seealso cref="Size"/>
186 /// <seealso cref="MaxSize"/> 186 /// <seealso cref="MaxSize"/>
187 /// <seealso cref="IsCountLimited"/> 187 /// <seealso cref="IsCountLimited"/>
188 /// <seealso cref="IsTimeLimited"/> 188 /// <seealso cref="IsTimeLimited"/>
189 bool IsSizeLimited { get; } 189 bool IsSizeLimited { get; }
190 190
191 /// <summary> 191 /// <summary>
192 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time. 192 /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
193 /// </summary> 193 /// </summary>
194 /// <value> 194 /// <value>
195 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements; 195 /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
196 /// otherwise, <see langword="false"/>. 196 /// otherwise, <see langword="false"/>.
197 /// </value> 197 /// </value>
198 /// <remarks> 198 /// <remarks>
199 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="Set"/> 199 /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="Set"/>
200 /// or <see cref="TryGetValue"/> methods in <see cref="ExpirationTime"/> , then element is automatically removed from 200 /// or <see cref="TryGetValue"/> methods in <see cref="ExpirationTime"/> , then element is automatically removed from
201 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may 201 /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
202 /// stay longer in cache. 202 /// stay longer in cache.
203 /// </remarks> 203 /// </remarks>
204 /// <seealso cref="ExpirationTime"/> 204 /// <seealso cref="ExpirationTime"/>
205 /// <seealso cref="PurgeExpired"/> 205 /// <seealso cref="PurgeExpired"/>
206 /// <seealso cref="IsCountLimited"/> 206 /// <seealso cref="IsCountLimited"/>
207 /// <seealso cref="IsSizeLimited"/> 207 /// <seealso cref="IsSizeLimited"/>
208 bool IsTimeLimited { get; } 208 bool IsTimeLimited { get; }
209 209
210 /// <summary> 210 /// <summary>
211 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>. 211 /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
212 /// </summary> 212 /// </summary>
213 /// <value> 213 /// <value>
214 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements; 214 /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
215 /// otherwise maximal allowed count of elements. 215 /// otherwise maximal allowed count of elements.
216 /// </value> 216 /// </value>
217 /// <remarks> 217 /// <remarks>
218 /// <para> 218 /// <para>
219 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 219 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
220 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 220 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
221 /// </para> 221 /// </para>
222 /// </remarks> 222 /// </remarks>
223 int MaxCount { get; set; } 223 int MaxCount { get; set; }
224 224
225 /// <summary> 225 /// <summary>
226 /// <para>Gets maximal allowed element size.</para> 226 /// <para>Gets maximal allowed element size.</para>
227 /// </summary> 227 /// </summary>
228 /// <value> 228 /// <value>
229 /// Maximal allowed element size. 229 /// Maximal allowed element size.
230 /// </value> 230 /// </value>
231 /// <remarks> 231 /// <remarks>
232 /// <para> 232 /// <para>
233 /// If element's size is larger than <see cref="MaxElementSize"/>, then element is 233 /// If element's size is larger than <see cref="MaxElementSize"/>, then element is
234 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>. 234 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
235 /// </para> 235 /// </para>
236 /// </remarks> 236 /// </remarks>
237 /// <seealso cref="Set"/> 237 /// <seealso cref="Set"/>
238 /// <seealso cref="IsSizeLimited"/> 238 /// <seealso cref="IsSizeLimited"/>
239 /// <seealso cref="Size"/> 239 /// <seealso cref="Size"/>
240 /// <seealso cref="MaxSize"/> 240 /// <seealso cref="MaxSize"/>
241 long MaxElementSize { get; } 241 long MaxElementSize { get; }
242 242
243 /// <summary> 243 /// <summary>
244 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 244 /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
245 /// </summary> 245 /// </summary>
246 /// <value> 246 /// <value>
247 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 247 /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
248 /// </value> 248 /// </value>
249 /// <remarks> 249 /// <remarks>
250 /// <para> 250 /// <para>
251 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure. 251 /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
252 /// </para> 252 /// </para>
253 /// <para> 253 /// <para>
254 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 254 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
255 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 255 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
256 /// </para> 256 /// </para>
257 /// </remarks> 257 /// </remarks>
258 /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception> 258 /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception>
259 /// <seealso cref="MaxElementSize"/> 259 /// <seealso cref="MaxElementSize"/>
260 /// <seealso cref="IsSizeLimited"/> 260 /// <seealso cref="IsSizeLimited"/>
261 /// <seealso cref="Size"/> 261 /// <seealso cref="Size"/>
262 long MaxSize { get; set; } 262 long MaxSize { get; set; }
263 263
264 /// <summary> 264 /// <summary>
265 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 265 /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
266 /// </summary> 266 /// </summary>
267 /// <value> 267 /// <value>
268 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>. 268 /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
269 /// </value> 269 /// </value>
270 /// <remarks> 270 /// <remarks>
271 /// <para> 271 /// <para>
272 /// Normally bytes, but can be any suitable unit of measure. 272 /// Normally bytes, but can be any suitable unit of measure.
273 /// </para> 273 /// </para>
274 /// <para> 274 /// <para>
275 /// Element's size is given when element is added or replaced by <see cref="Set"/> method. 275 /// Element's size is given when element is added or replaced by <see cref="Set"/> method.
276 /// </para> 276 /// </para>
277 /// <para> 277 /// <para>
278 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 278 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
279 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element. 279 /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
280 /// </para> 280 /// </para>
281 /// </remarks> 281 /// </remarks>
282 /// <seealso cref="MaxElementSize"/> 282 /// <seealso cref="MaxElementSize"/>
283 /// <seealso cref="IsSizeLimited"/> 283 /// <seealso cref="IsSizeLimited"/>
284 /// <seealso cref="MaxSize"/> 284 /// <seealso cref="MaxSize"/>
285 /// <seealso cref="IsCountLimited"/> 285 /// <seealso cref="IsCountLimited"/>
286 /// <seealso cref="ExpirationTime"/> 286 /// <seealso cref="ExpirationTime"/>
287 long Size { get; } 287 long Size { get; }
288 288
289 /// <summary> 289 /// <summary>
290 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 290 /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
291 /// </summary> 291 /// </summary>
292 /// <value> 292 /// <value>
293 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>. 293 /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
294 /// </value> 294 /// </value>
295 /// <remarks> 295 /// <remarks>
296 /// <para> 296 /// <para>
297 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/> 297 /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
298 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to 298 /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
299 /// <see cref="ICnmCache{TKey,TValue}"/>. 299 /// <see cref="ICnmCache{TKey,TValue}"/>.
300 /// </para> 300 /// </para>
301 /// </remarks> 301 /// </remarks>
302 /// <seealso cref="IsSynchronized"/> 302 /// <seealso cref="IsSynchronized"/>
303 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/> 303 /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
304 object SyncRoot { get; } 304 object SyncRoot { get; }
305 305
306 /// <summary> 306 /// <summary>
307 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>. 307 /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
308 /// </summary> 308 /// </summary>
309 /// <seealso cref="Set"/> 309 /// <seealso cref="Set"/>
310 /// <seealso cref="Remove"/> 310 /// <seealso cref="Remove"/>
311 /// <seealso cref="RemoveRange"/> 311 /// <seealso cref="RemoveRange"/>
312 /// <seealso cref="TryGetValue"/> 312 /// <seealso cref="TryGetValue"/>
313 /// <seealso cref="PurgeExpired"/> 313 /// <seealso cref="PurgeExpired"/>
314 void Clear(); 314 void Clear();
315 315
316 /// <summary> 316 /// <summary>
317 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>. 317 /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
318 /// </summary> 318 /// </summary>
319 /// <remarks> 319 /// <remarks>
320 /// <para> 320 /// <para>
321 /// Element becomes expired when last access time to it has been longer time than <see cref="ExpirationTime"/>. 321 /// Element becomes expired when last access time to it has been longer time than <see cref="ExpirationTime"/>.
322 /// </para> 322 /// </para>
323 /// <para> 323 /// <para>
324 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements 324 /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
325 /// may stay longer than <see cref="ExpirationTime"/> in the cache. 325 /// may stay longer than <see cref="ExpirationTime"/> in the cache.
326 /// </para> 326 /// </para>
327 /// </remarks> 327 /// </remarks>
328 /// <seealso cref="IsTimeLimited"/> 328 /// <seealso cref="IsTimeLimited"/>
329 /// <seealso cref="ExpirationTime"/> 329 /// <seealso cref="ExpirationTime"/>
330 /// <seealso cref="Set"/> 330 /// <seealso cref="Set"/>
331 /// <seealso cref="Remove"/> 331 /// <seealso cref="Remove"/>
332 /// <seealso cref="RemoveRange"/> 332 /// <seealso cref="RemoveRange"/>
333 /// <seealso cref="TryGetValue"/> 333 /// <seealso cref="TryGetValue"/>
334 /// <seealso cref="Clear"/> 334 /// <seealso cref="Clear"/>
335 void PurgeExpired(); 335 void PurgeExpired();
336 336
337 /// <summary> 337 /// <summary>
338 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 338 /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
339 /// </summary> 339 /// </summary>
340 /// <param name="key"> 340 /// <param name="key">
341 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 341 /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
342 /// </param> 342 /// </param>
343 /// <exception cref="ArgumentNullException"> 343 /// <exception cref="ArgumentNullException">
344 /// <paramref name="key"/> is <see langword="null"/>. 344 /// <paramref name="key"/> is <see langword="null"/>.
345 /// </exception> 345 /// </exception>
346 /// <seealso cref="Set"/> 346 /// <seealso cref="Set"/>
347 /// <seealso cref="RemoveRange"/> 347 /// <seealso cref="RemoveRange"/>
348 /// <seealso cref="TryGetValue"/> 348 /// <seealso cref="TryGetValue"/>
349 /// <seealso cref="Clear"/> 349 /// <seealso cref="Clear"/>
350 /// <seealso cref="PurgeExpired"/> 350 /// <seealso cref="PurgeExpired"/>
351 void Remove( TKey key ); 351 void Remove( TKey key );
352 352
353 /// <summary> 353 /// <summary>
354 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>. 354 /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
355 /// </summary> 355 /// </summary>
356 /// <param name="keys"> 356 /// <param name="keys">
357 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>. 357 /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
358 /// </param> 358 /// </param>
359 /// <exception cref="ArgumentNullException"> 359 /// <exception cref="ArgumentNullException">
360 /// <paramref name="keys"/> is <see langword="null"/>. 360 /// <paramref name="keys"/> is <see langword="null"/>.
361 /// </exception> 361 /// </exception>
362 /// <seealso cref="Set"/> 362 /// <seealso cref="Set"/>
363 /// <seealso cref="Remove"/> 363 /// <seealso cref="Remove"/>
364 /// <seealso cref="TryGetValue"/> 364 /// <seealso cref="TryGetValue"/>
365 /// <seealso cref="Clear"/> 365 /// <seealso cref="Clear"/>
366 /// <seealso cref="PurgeExpired"/> 366 /// <seealso cref="PurgeExpired"/>
367 void RemoveRange( IEnumerable<TKey> keys ); 367 void RemoveRange( IEnumerable<TKey> keys );
368 368
369 /// <summary> 369 /// <summary>
370 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to 370 /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
371 /// <see cref="ICnmCache{TKey,TValue}"/>. 371 /// <see cref="ICnmCache{TKey,TValue}"/>.
372 /// </summary> 372 /// </summary>
373 /// <param name="key"> 373 /// <param name="key">
374 /// The object used as the key of the element. Can't be <see langword="null"/> reference. 374 /// The object used as the key of the element. Can't be <see langword="null"/> reference.
375 /// </param> 375 /// </param>
376 /// <param name="value"> 376 /// <param name="value">
377 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed. 377 /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
378 /// </param> 378 /// </param>
379 /// <param name="size"> 379 /// <param name="size">
380 /// The element's size. Normally bytes, but can be any suitable unit of measure. 380 /// The element's size. Normally bytes, but can be any suitable unit of measure.
381 /// </param> 381 /// </param>
382 /// <returns> 382 /// <returns>
383 /// <see langword="true"/> if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>; 383 /// <see langword="true"/> if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
384 /// otherwise <see langword="false"/>. 384 /// otherwise <see langword="false"/>.
385 /// </returns> 385 /// </returns>
386 /// <exception cref="ArgumentNullException"> 386 /// <exception cref="ArgumentNullException">
387 /// <paramref name="key"/>is <see langword="null"/>. 387 /// <paramref name="key"/>is <see langword="null"/>.
388 /// </exception> 388 /// </exception>
389 /// <exception cref="ArgumentOutOfRangeException"> 389 /// <exception cref="ArgumentOutOfRangeException">
390 /// The element's <paramref name="size"/> is less than 0. 390 /// The element's <paramref name="size"/> is less than 0.
391 /// </exception> 391 /// </exception>
392 /// <remarks> 392 /// <remarks>
393 /// <para> 393 /// <para>
394 /// If element's <paramref name="size"/> is larger than <see cref="MaxElementSize"/>, then element is 394 /// If element's <paramref name="size"/> is larger than <see cref="MaxElementSize"/>, then element is
395 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is 395 /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
396 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>. 396 /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
397 /// </para> 397 /// </para>
398 /// <para> 398 /// <para>
399 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements, 399 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
400 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 400 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
401 /// </para> 401 /// </para>
402 /// <para> 402 /// <para>
403 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count, 403 /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
404 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element. 404 /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
405 /// </para> 405 /// </para>
406 /// </remarks> 406 /// </remarks>
407 /// <seealso cref="IsSizeLimited"/> 407 /// <seealso cref="IsSizeLimited"/>
408 /// <seealso cref="IsCountLimited"/> 408 /// <seealso cref="IsCountLimited"/>
409 /// <seealso cref="Remove"/> 409 /// <seealso cref="Remove"/>
410 /// <seealso cref="RemoveRange"/> 410 /// <seealso cref="RemoveRange"/>
411 /// <seealso cref="TryGetValue"/> 411 /// <seealso cref="TryGetValue"/>
412 /// <seealso cref="Clear"/> 412 /// <seealso cref="Clear"/>
413 /// <seealso cref="PurgeExpired"/> 413 /// <seealso cref="PurgeExpired"/>
414 bool Set( TKey key, TValue value, long size ); 414 bool Set( TKey key, TValue value, long size );
415 415
416 /// <summary> 416 /// <summary>
417 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>. 417 /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
418 /// </summary> 418 /// </summary>
419 /// <returns> 419 /// <returns>
420 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with 420 /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
421 /// the specified key; otherwise, <see langword="false"/>. 421 /// the specified key; otherwise, <see langword="false"/>.
422 /// </returns> 422 /// </returns>
423 /// <param name="key"> 423 /// <param name="key">
424 /// The key whose <paramref name="value"/> to get. 424 /// The key whose <paramref name="value"/> to get.
425 /// </param> 425 /// </param>
426 /// <param name="value"> 426 /// <param name="value">
427 /// When this method returns, the value associated with the specified <paramref name="key"/>, 427 /// When this method returns, the value associated with the specified <paramref name="key"/>,
428 /// if the <paramref name="key"/> is found; otherwise, the 428 /// if the <paramref name="key"/> is found; otherwise, the
429 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized. 429 /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
430 /// </param> 430 /// </param>
431 /// <exception cref="ArgumentNullException"> 431 /// <exception cref="ArgumentNullException">
432 /// <paramref name="key"/>is <see langword="null"/>. 432 /// <paramref name="key"/>is <see langword="null"/>.
433 /// </exception> 433 /// </exception>
434 /// <seealso cref="Set"/> 434 /// <seealso cref="Set"/>
435 /// <seealso cref="Remove"/> 435 /// <seealso cref="Remove"/>
436 /// <seealso cref="RemoveRange"/> 436 /// <seealso cref="RemoveRange"/>
437 /// <seealso cref="Clear"/> 437 /// <seealso cref="Clear"/>
438 /// <seealso cref="PurgeExpired"/> 438 /// <seealso cref="PurgeExpired"/>
439 bool TryGetValue( TKey key, out TValue value ); 439 bool TryGetValue( TKey key, out TValue value );
440 } 440 }
441} 441}
diff --git a/OpenSim/Framework/PrimeNumberHelper.cs b/OpenSim/Framework/PrimeNumberHelper.cs
index e4bf615..f533f4a 100644
--- a/OpenSim/Framework/PrimeNumberHelper.cs
+++ b/OpenSim/Framework/PrimeNumberHelper.cs
@@ -1,98 +1,98 @@
1// -------------------------------------------------------------------------------------------------------------------- 1// --------------------------------------------------------------------------------------------------------------------
2// <copyright company="" file="PrimeNumberHelper.cs"> 2// <copyright company="" file="PrimeNumberHelper.cs">
3// 3//
4// </copyright> 4// </copyright>
5// <summary> 5// <summary>
6// 6//
7// </summary> 7// </summary>
8// 8//
9// -------------------------------------------------------------------------------------------------------------------- 9// --------------------------------------------------------------------------------------------------------------------
10 10
11using System; 11using System;
12 12
13namespace OpenSim.Framework 13namespace OpenSim.Framework
14{ 14{
15 /// <summary> 15 /// <summary>
16 /// Utility class that is used to find small prime numbers and test is number prime number. 16 /// Utility class that is used to find small prime numbers and test is number prime number.
17 /// </summary> 17 /// </summary>
18 public static class PrimeNumberHelper 18 public static class PrimeNumberHelper
19 { 19 {
20 /// <summary> 20 /// <summary>
21 /// Precalculated prime numbers. 21 /// Precalculated prime numbers.
22 /// </summary> 22 /// </summary>
23 private static readonly int[] Primes = new int[] 23 private static readonly int[] Primes = new int[]
24 { 24 {
25 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 25 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239,
26 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 26 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333,
27 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 27 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
28 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 28 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431,
29 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 29 90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449,
30 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 30 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
31 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 31 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559,
32 5999471, 7199369 32 5999471, 7199369
33 }; 33 };
34 34
35 /// <summary> 35 /// <summary>
36 /// Get prime number that is equal or larger than <see cref="min"/>. 36 /// Get prime number that is equal or larger than <see cref="min"/>.
37 /// </summary> 37 /// </summary>
38 /// <param name="min"> 38 /// <param name="min">
39 /// Minimal returned prime number. 39 /// Minimal returned prime number.
40 /// </param> 40 /// </param>
41 /// <returns> 41 /// <returns>
42 /// Primer number that is equal or larger than <see cref="min"/>. If <see cref="min"/> is too large, return -1. 42 /// Primer number that is equal or larger than <see cref="min"/>. If <see cref="min"/> is too large, return -1.
43 /// </returns> 43 /// </returns>
44 public static int GetPrime( int min ) 44 public static int GetPrime( int min )
45 { 45 {
46 if( min <= 2 ) 46 if( min <= 2 )
47 return 2; 47 return 2;
48 48
49 if( Primes[ Primes.Length - 1 ] < min ) 49 if( Primes[ Primes.Length - 1 ] < min )
50 { 50 {
51 for( int i = min | 1 ; i < 0x7FFFFFFF ; i += 2 ) 51 for( int i = min | 1 ; i < 0x7FFFFFFF ; i += 2 )
52 { 52 {
53 if( IsPrime( i ) ) 53 if( IsPrime( i ) )
54 return i; 54 return i;
55 } 55 }
56 56
57 return -1; 57 return -1;
58 } 58 }
59 59
60 for( int i = Primes.Length - 2 ; i >= 0 ; i-- ) 60 for( int i = Primes.Length - 2 ; i >= 0 ; i-- )
61 { 61 {
62 if( min == Primes[ i ] ) 62 if( min == Primes[ i ] )
63 return min; 63 return min;
64 64
65 if( min > Primes[ i ] ) 65 if( min > Primes[ i ] )
66 return Primes[ i + 1 ]; 66 return Primes[ i + 1 ];
67 } 67 }
68 68
69 return 2; 69 return 2;
70 } 70 }
71 71
72 /// <summary> 72 /// <summary>
73 /// Just basic Sieve of Eratosthenes prime number test. 73 /// Just basic Sieve of Eratosthenes prime number test.
74 /// </summary> 74 /// </summary>
75 /// <param name="candinate"> 75 /// <param name="candinate">
76 /// Number that is tested. 76 /// Number that is tested.
77 /// </param> 77 /// </param>
78 /// <returns> 78 /// <returns>
79 /// true, if <see cref="candinate"/> is prime number; otherwise false. 79 /// true, if <see cref="candinate"/> is prime number; otherwise false.
80 /// </returns> 80 /// </returns>
81 public static bool IsPrime( int candinate ) 81 public static bool IsPrime( int candinate )
82 { 82 {
83 if( (candinate & 1) == 0 ) 83 if( (candinate & 1) == 0 )
84 84
85 // Even number - only prime if 2 85 // Even number - only prime if 2
86 return candinate == 2; 86 return candinate == 2;
87 87
88 int upperBound = (int) Math.Sqrt( candinate ); 88 int upperBound = (int) Math.Sqrt( candinate );
89 for( int i = 3 ; i < upperBound ; i += 2 ) 89 for( int i = 3 ; i < upperBound ; i += 2 )
90 { 90 {
91 if( candinate % i == 0 ) 91 if( candinate % i == 0 )
92 return false; 92 return false;
93 } 93 }
94 94
95 return true; 95 return true;
96 } 96 }
97 } 97 }
98} 98}