diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/CnmMemoryCache.cs | 3704 | ||||
-rw-r--r-- | OpenSim/Framework/CnmSynchronizedCache.cs | 1492 | ||||
-rw-r--r-- | OpenSim/Framework/ICnmCache.cs | 882 | ||||
-rw-r--r-- | OpenSim/Framework/PrimeNumberHelper.cs | 196 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | 764 |
5 files changed, 3519 insertions, 3519 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 | ||
10 | using System; | 10 | using System; |
11 | using System.Collections; | 11 | using System.Collections; |
12 | using System.Collections.Generic; | 12 | using System.Collections.Generic; |
13 | using System.Diagnostics; | 13 | using System.Diagnostics; |
14 | 14 | ||
15 | namespace OpenSim.Framework | 15 | namespace 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 | */ |
27 | using System; | 27 | using System; |
28 | using System.Collections; | 28 | using System.Collections; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Threading; | 30 | using System.Threading; |
31 | 31 | ||
32 | namespace OpenSim.Framework | 32 | namespace 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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | 30 | ||
31 | namespace OpenSim.Framework | 31 | namespace 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 | ||
11 | using System; | 11 | using System; |
12 | 12 | ||
13 | namespace OpenSim.Framework | 13 | namespace 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 | } |
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index 00a8143..bbc9c9b 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs | |||
@@ -1,382 +1,382 @@ | |||
1 | // -------------------------------------------------------------------------------------------------------------------- | 1 | // -------------------------------------------------------------------------------------------------------------------- |
2 | // <copyright company="" file="CenomeAssetCache.cs"> | 2 | // <copyright company="" file="CenomeAssetCache.cs"> |
3 | // | 3 | // |
4 | // </copyright> | 4 | // </copyright> |
5 | // <summary> | 5 | // <summary> |
6 | // | 6 | // |
7 | // </summary> | 7 | // </summary> |
8 | // | 8 | // |
9 | // -------------------------------------------------------------------------------------------------------------------- | 9 | // -------------------------------------------------------------------------------------------------------------------- |
10 | using System; | 10 | using System; |
11 | using System.Reflection; | 11 | using System.Reflection; |
12 | using log4net; | 12 | using log4net; |
13 | using Nini.Config; | 13 | using Nini.Config; |
14 | using OpenSim.Framework; | 14 | using OpenSim.Framework; |
15 | using OpenSim.Region.Framework.Interfaces; | 15 | using OpenSim.Region.Framework.Interfaces; |
16 | using OpenSim.Region.Framework.Scenes; | 16 | using OpenSim.Region.Framework.Scenes; |
17 | 17 | ||
18 | namespace OpenSim.Region.CoreModules.Asset | 18 | namespace OpenSim.Region.CoreModules.Asset |
19 | { | 19 | { |
20 | /// <summary> | 20 | /// <summary> |
21 | /// Cenome memory asset cache. | 21 | /// Cenome memory asset cache. |
22 | /// </summary> | 22 | /// </summary> |
23 | /// <remarks> | 23 | /// <remarks> |
24 | /// <para> | 24 | /// <para> |
25 | /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache". | 25 | /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache". |
26 | /// When cache is successfully enable log should have message | 26 | /// When cache is successfully enable log should have message |
27 | /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)". | 27 | /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)". |
28 | /// </para> | 28 | /// </para> |
29 | /// <para> | 29 | /// <para> |
30 | /// Cache's size is limited by two parameters: | 30 | /// Cache's size is limited by two parameters: |
31 | /// maximal allowed size in bytes and maximal allowed asset count. When new asset | 31 | /// maximal allowed size in bytes and maximal allowed asset count. When new asset |
32 | /// is added to cache that have achieved either size or count limitation, cache | 32 | /// is added to cache that have achieved either size or count limitation, cache |
33 | /// will automatically remove less recently used assets from cache. Additionally | 33 | /// will automatically remove less recently used assets from cache. Additionally |
34 | /// asset's lifetime is controlled by expiration time. | 34 | /// asset's lifetime is controlled by expiration time. |
35 | /// </para> | 35 | /// </para> |
36 | /// <para> | 36 | /// <para> |
37 | /// <list type="table"> | 37 | /// <list type="table"> |
38 | /// <listheader> | 38 | /// <listheader> |
39 | /// <term>Configuration</term> | 39 | /// <term>Configuration</term> |
40 | /// <description>Description</description> | 40 | /// <description>Description</description> |
41 | /// </listheader> | 41 | /// </listheader> |
42 | /// <item> | 42 | /// <item> |
43 | /// <term>MaxSize</term> | 43 | /// <term>MaxSize</term> |
44 | /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description> | 44 | /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description> |
45 | /// </item> | 45 | /// </item> |
46 | /// <item> | 46 | /// <item> |
47 | /// <term>MaxCount</term> | 47 | /// <term>MaxCount</term> |
48 | /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description> | 48 | /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description> |
49 | /// </item> | 49 | /// </item> |
50 | /// <item> | 50 | /// <item> |
51 | /// <term>ExpirationTime</term> | 51 | /// <term>ExpirationTime</term> |
52 | /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description> | 52 | /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description> |
53 | /// </item> | 53 | /// </item> |
54 | /// </list> | 54 | /// </list> |
55 | /// </para> | 55 | /// </para> |
56 | /// </remarks> | 56 | /// </remarks> |
57 | /// <example> | 57 | /// <example> |
58 | /// Enabling Cenome Asset Cache: | 58 | /// Enabling Cenome Asset Cache: |
59 | /// <code> | 59 | /// <code> |
60 | /// [Modules] | 60 | /// [Modules] |
61 | /// AssetCaching = "CenomeMemoryAssetCache" | 61 | /// AssetCaching = "CenomeMemoryAssetCache" |
62 | /// </code> | 62 | /// </code> |
63 | /// Setting size and expiration time limitations: | 63 | /// Setting size and expiration time limitations: |
64 | /// <code> | 64 | /// <code> |
65 | /// [AssetService] | 65 | /// [AssetService] |
66 | /// ; 256 MB (default: 134217728) | 66 | /// ; 256 MB (default: 134217728) |
67 | /// MaxSize = 268435456 | 67 | /// MaxSize = 268435456 |
68 | /// ; How many assets it is possible to store cache (default: 4096) | 68 | /// ; How many assets it is possible to store cache (default: 4096) |
69 | /// MaxCount = 16384 | 69 | /// MaxCount = 16384 |
70 | /// ; Expiration time - 1 hour (default: 30 minutes) | 70 | /// ; Expiration time - 1 hour (default: 30 minutes) |
71 | /// ExpirationTime = 60 | 71 | /// ExpirationTime = 60 |
72 | /// </code> | 72 | /// </code> |
73 | /// </example> | 73 | /// </example> |
74 | public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule | 74 | public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule |
75 | { | 75 | { |
76 | /// <summary> | 76 | /// <summary> |
77 | /// Cache's default maximal asset count. | 77 | /// Cache's default maximal asset count. |
78 | /// </summary> | 78 | /// </summary> |
79 | /// <remarks> | 79 | /// <remarks> |
80 | /// <para> | 80 | /// <para> |
81 | /// Assuming that average asset size is about 32768 bytes. | 81 | /// Assuming that average asset size is about 32768 bytes. |
82 | /// </para> | 82 | /// </para> |
83 | /// </remarks> | 83 | /// </remarks> |
84 | public const int DefaultMaxCount = 4096; | 84 | public const int DefaultMaxCount = 4096; |
85 | 85 | ||
86 | /// <summary> | 86 | /// <summary> |
87 | /// Default maximal size of the cache in bytes | 87 | /// Default maximal size of the cache in bytes |
88 | /// </summary> | 88 | /// </summary> |
89 | /// <remarks> | 89 | /// <remarks> |
90 | /// <para> | 90 | /// <para> |
91 | /// 128MB = 128 * 1024^2 = 134 217 728 bytes. | 91 | /// 128MB = 128 * 1024^2 = 134 217 728 bytes. |
92 | /// </para> | 92 | /// </para> |
93 | /// </remarks> | 93 | /// </remarks> |
94 | public const long DefaultMaxSize = 134217728; | 94 | public const long DefaultMaxSize = 134217728; |
95 | 95 | ||
96 | /// <summary> | 96 | /// <summary> |
97 | /// Asset's default expiration time in the cache. | 97 | /// Asset's default expiration time in the cache. |
98 | /// </summary> | 98 | /// </summary> |
99 | public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 ); | 99 | public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes( 30.0 ); |
100 | 100 | ||
101 | /// <summary> | 101 | /// <summary> |
102 | /// Log manager instance. | 102 | /// Log manager instance. |
103 | /// </summary> | 103 | /// </summary> |
104 | private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ); | 104 | private static readonly ILog Log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType ); |
105 | 105 | ||
106 | /// <summary> | 106 | /// <summary> |
107 | /// Cache object. | 107 | /// Cache object. |
108 | /// </summary> | 108 | /// </summary> |
109 | private ICnmCache<string, AssetBase> m_cache; | 109 | private ICnmCache<string, AssetBase> m_cache; |
110 | 110 | ||
111 | /// <summary> | 111 | /// <summary> |
112 | /// Count of cache commands | 112 | /// Count of cache commands |
113 | /// </summary> | 113 | /// </summary> |
114 | private int m_cachedCount; | 114 | private int m_cachedCount; |
115 | 115 | ||
116 | /// <summary> | 116 | /// <summary> |
117 | /// How many gets before dumping statistics | 117 | /// How many gets before dumping statistics |
118 | /// </summary> | 118 | /// </summary> |
119 | /// <remarks> | 119 | /// <remarks> |
120 | /// If 0 or less, then disabled. | 120 | /// If 0 or less, then disabled. |
121 | /// </remarks> | 121 | /// </remarks> |
122 | private int m_debugEpoch; | 122 | private int m_debugEpoch; |
123 | 123 | ||
124 | /// <summary> | 124 | /// <summary> |
125 | /// Is Cenome asset cache enabled. | 125 | /// Is Cenome asset cache enabled. |
126 | /// </summary> | 126 | /// </summary> |
127 | private bool m_enabled; | 127 | private bool m_enabled; |
128 | 128 | ||
129 | /// <summary> | 129 | /// <summary> |
130 | /// Count of get requests | 130 | /// Count of get requests |
131 | /// </summary> | 131 | /// </summary> |
132 | private int m_getCount; | 132 | private int m_getCount; |
133 | 133 | ||
134 | /// <summary> | 134 | /// <summary> |
135 | /// How many hits | 135 | /// How many hits |
136 | /// </summary> | 136 | /// </summary> |
137 | private int m_hitCount; | 137 | private int m_hitCount; |
138 | 138 | ||
139 | /// <summary> | 139 | /// <summary> |
140 | /// Initialize asset cache module with default parameters. | 140 | /// Initialize asset cache module with default parameters. |
141 | /// </summary> | 141 | /// </summary> |
142 | public void Initialize() | 142 | public void Initialize() |
143 | { | 143 | { |
144 | Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime ); | 144 | Initialize( DefaultMaxSize, DefaultMaxCount, DefaultExpirationTime ); |
145 | } | 145 | } |
146 | 146 | ||
147 | /// <summary> | 147 | /// <summary> |
148 | /// Initialize asset cache module, with custom parameters. | 148 | /// Initialize asset cache module, with custom parameters. |
149 | /// </summary> | 149 | /// </summary> |
150 | /// <param name="maximalSize"> | 150 | /// <param name="maximalSize"> |
151 | /// Cache's maximal size in bytes. | 151 | /// Cache's maximal size in bytes. |
152 | /// </param> | 152 | /// </param> |
153 | /// <param name="maximalCount"> | 153 | /// <param name="maximalCount"> |
154 | /// Cache's maximal count of assets. | 154 | /// Cache's maximal count of assets. |
155 | /// </param> | 155 | /// </param> |
156 | /// <param name="expirationTime"> | 156 | /// <param name="expirationTime"> |
157 | /// Asset's expiration time. | 157 | /// Asset's expiration time. |
158 | /// </param> | 158 | /// </param> |
159 | public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime ) | 159 | public void Initialize( long maximalSize, int maximalCount, TimeSpan expirationTime ) |
160 | { | 160 | { |
161 | if( maximalSize <= 0 || maximalCount <= 0 ) | 161 | if( maximalSize <= 0 || maximalCount <= 0 ) |
162 | { | 162 | { |
163 | Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." ); | 163 | Log.Info( "[ASSET CACHE]: Cenome asset cache is not enabled." ); |
164 | m_enabled = false; | 164 | m_enabled = false; |
165 | return; | 165 | return; |
166 | } | 166 | } |
167 | 167 | ||
168 | if( expirationTime <= TimeSpan.Zero ) | 168 | if( expirationTime <= TimeSpan.Zero ) |
169 | { | 169 | { |
170 | // Disable expiration time | 170 | // Disable expiration time |
171 | expirationTime = TimeSpan.MaxValue; | 171 | expirationTime = TimeSpan.MaxValue; |
172 | } | 172 | } |
173 | 173 | ||
174 | // Create cache and add synchronization wrapper over it | 174 | // Create cache and add synchronization wrapper over it |
175 | m_cache = | 175 | m_cache = |
176 | CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>( | 176 | CnmSynchronizedCache<string, AssetBase>.Synchronized( new CnmMemoryCache<string, AssetBase>( |
177 | maximalSize, maximalCount, expirationTime ) ); | 177 | maximalSize, maximalCount, expirationTime ) ); |
178 | m_enabled = true; | 178 | m_enabled = true; |
179 | Log.InfoFormat( | 179 | Log.InfoFormat( |
180 | "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})", | 180 | "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})", |
181 | maximalSize, | 181 | maximalSize, |
182 | maximalCount, | 182 | maximalCount, |
183 | expirationTime ); | 183 | expirationTime ); |
184 | } | 184 | } |
185 | 185 | ||
186 | #region IImprovedAssetCache Members | 186 | #region IImprovedAssetCache Members |
187 | 187 | ||
188 | /// <summary> | 188 | /// <summary> |
189 | /// Cache asset. | 189 | /// Cache asset. |
190 | /// </summary> | 190 | /// </summary> |
191 | /// <param name="asset"> | 191 | /// <param name="asset"> |
192 | /// The asset that is being cached. | 192 | /// The asset that is being cached. |
193 | /// </param> | 193 | /// </param> |
194 | public void Cache( AssetBase asset ) | 194 | public void Cache( AssetBase asset ) |
195 | { | 195 | { |
196 | long size = asset.Data != null ? asset.Data.Length : 1; | 196 | long size = asset.Data != null ? asset.Data.Length : 1; |
197 | m_cache.Set( asset.ID, asset, size ); | 197 | m_cache.Set( asset.ID, asset, size ); |
198 | m_cachedCount++; | 198 | m_cachedCount++; |
199 | } | 199 | } |
200 | 200 | ||
201 | /// <summary> | 201 | /// <summary> |
202 | /// Clear asset cache. | 202 | /// Clear asset cache. |
203 | /// </summary> | 203 | /// </summary> |
204 | public void Clear() | 204 | public void Clear() |
205 | { | 205 | { |
206 | m_cache.Clear(); | 206 | m_cache.Clear(); |
207 | } | 207 | } |
208 | 208 | ||
209 | /// <summary> | 209 | /// <summary> |
210 | /// Expire (remove) asset stored to cache. | 210 | /// Expire (remove) asset stored to cache. |
211 | /// </summary> | 211 | /// </summary> |
212 | /// <param name="id"> | 212 | /// <param name="id"> |
213 | /// The expired asset's id. | 213 | /// The expired asset's id. |
214 | /// </param> | 214 | /// </param> |
215 | public void Expire( string id ) | 215 | public void Expire( string id ) |
216 | { | 216 | { |
217 | m_cache.Remove( id ); | 217 | m_cache.Remove( id ); |
218 | } | 218 | } |
219 | 219 | ||
220 | /// <summary> | 220 | /// <summary> |
221 | /// Get asset stored | 221 | /// Get asset stored |
222 | /// </summary> | 222 | /// </summary> |
223 | /// <param name="id"> | 223 | /// <param name="id"> |
224 | /// The asset's id. | 224 | /// The asset's id. |
225 | /// </param> | 225 | /// </param> |
226 | /// <returns> | 226 | /// <returns> |
227 | /// Asset if it is found from cache; otherwise <see langword="null"/>. | 227 | /// Asset if it is found from cache; otherwise <see langword="null"/>. |
228 | /// </returns> | 228 | /// </returns> |
229 | /// <remarks> | 229 | /// <remarks> |
230 | /// <para> | 230 | /// <para> |
231 | /// Caller should always check that is return value <see langword="null"/>. | 231 | /// Caller should always check that is return value <see langword="null"/>. |
232 | /// Cache doesn't guarantee in any situation that asset is stored to it. | 232 | /// Cache doesn't guarantee in any situation that asset is stored to it. |
233 | /// </para> | 233 | /// </para> |
234 | /// </remarks> | 234 | /// </remarks> |
235 | public AssetBase Get( string id ) | 235 | public AssetBase Get( string id ) |
236 | { | 236 | { |
237 | m_getCount++; | 237 | m_getCount++; |
238 | AssetBase assetBase; | 238 | AssetBase assetBase; |
239 | if( m_cache.TryGetValue( id, out assetBase ) ) | 239 | if( m_cache.TryGetValue( id, out assetBase ) ) |
240 | m_hitCount++; | 240 | m_hitCount++; |
241 | 241 | ||
242 | if( m_getCount == m_debugEpoch ) | 242 | if( m_getCount == m_debugEpoch ) |
243 | { | 243 | { |
244 | Log.InfoFormat( | 244 | Log.InfoFormat( |
245 | "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes", | 245 | "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes", |
246 | m_cachedCount, | 246 | m_cachedCount, |
247 | m_getCount, | 247 | m_getCount, |
248 | ((double) m_hitCount / m_getCount) * 100.0, | 248 | ((double) m_hitCount / m_getCount) * 100.0, |
249 | m_cache.Size, | 249 | m_cache.Size, |
250 | m_cache.Size / m_cache.Count ); | 250 | m_cache.Size / m_cache.Count ); |
251 | m_getCount = 0; | 251 | m_getCount = 0; |
252 | m_hitCount = 0; | 252 | m_hitCount = 0; |
253 | m_cachedCount = 0; | 253 | m_cachedCount = 0; |
254 | } | 254 | } |
255 | 255 | ||
256 | return assetBase; | 256 | return assetBase; |
257 | } | 257 | } |
258 | 258 | ||
259 | #endregion | 259 | #endregion |
260 | 260 | ||
261 | #region ISharedRegionModule Members | 261 | #region ISharedRegionModule Members |
262 | 262 | ||
263 | /// <summary> | 263 | /// <summary> |
264 | /// Gets region module's name. | 264 | /// Gets region module's name. |
265 | /// </summary> | 265 | /// </summary> |
266 | public string Name | 266 | public string Name |
267 | { | 267 | { |
268 | get { return "CenomeMemoryAssetCache"; } | 268 | get { return "CenomeMemoryAssetCache"; } |
269 | } | 269 | } |
270 | 270 | ||
271 | /// <summary> | 271 | /// <summary> |
272 | /// New region is being added to server. | 272 | /// New region is being added to server. |
273 | /// </summary> | 273 | /// </summary> |
274 | /// <param name="scene"> | 274 | /// <param name="scene"> |
275 | /// Region's scene. | 275 | /// Region's scene. |
276 | /// </param> | 276 | /// </param> |
277 | public void AddRegion( Scene scene ) | 277 | public void AddRegion( Scene scene ) |
278 | { | 278 | { |
279 | if( m_enabled ) | 279 | if( m_enabled ) |
280 | scene.RegisterModuleInterface<IImprovedAssetCache>( this ); | 280 | scene.RegisterModuleInterface<IImprovedAssetCache>( this ); |
281 | } | 281 | } |
282 | 282 | ||
283 | /// <summary> | 283 | /// <summary> |
284 | /// Close region module. | 284 | /// Close region module. |
285 | /// </summary> | 285 | /// </summary> |
286 | public void Close() | 286 | public void Close() |
287 | { | 287 | { |
288 | m_enabled = false; | 288 | m_enabled = false; |
289 | m_cache.Clear(); | 289 | m_cache.Clear(); |
290 | m_cache = null; | 290 | m_cache = null; |
291 | } | 291 | } |
292 | 292 | ||
293 | /// <summary> | 293 | /// <summary> |
294 | /// Initialize region module. | 294 | /// Initialize region module. |
295 | /// </summary> | 295 | /// </summary> |
296 | /// <param name="source"> | 296 | /// <param name="source"> |
297 | /// Configuration source. | 297 | /// Configuration source. |
298 | /// </param> | 298 | /// </param> |
299 | public void Initialise( IConfigSource source ) | 299 | public void Initialise( IConfigSource source ) |
300 | { | 300 | { |
301 | m_cache = null; | 301 | m_cache = null; |
302 | m_enabled = false; | 302 | m_enabled = false; |
303 | 303 | ||
304 | IConfig moduleConfig = source.Configs[ "Modules" ]; | 304 | IConfig moduleConfig = source.Configs[ "Modules" ]; |
305 | if( moduleConfig == null ) | 305 | if( moduleConfig == null ) |
306 | return; | 306 | return; |
307 | 307 | ||
308 | string name = moduleConfig.GetString( "AssetCaching" ); | 308 | string name = moduleConfig.GetString( "AssetCaching" ); |
309 | Log.DebugFormat( "[XXX] name = {0} (this module's name: {1}", name, Name ); | 309 | Log.DebugFormat( "[XXX] name = {0} (this module's name: {1}", name, Name ); |
310 | 310 | ||
311 | if( name != Name ) | 311 | if( name != Name ) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | // This module is used | 314 | // This module is used |
315 | long maxSize = DefaultMaxSize; | 315 | long maxSize = DefaultMaxSize; |
316 | int maxCount = DefaultMaxCount; | 316 | int maxCount = DefaultMaxCount; |
317 | TimeSpan expirationTime = DefaultExpirationTime; | 317 | TimeSpan expirationTime = DefaultExpirationTime; |
318 | 318 | ||
319 | IConfig assetConfig = source.Configs[ "AssetCache" ]; | 319 | IConfig assetConfig = source.Configs[ "AssetCache" ]; |
320 | if( assetConfig != null ) | 320 | if( assetConfig != null ) |
321 | { | 321 | { |
322 | // Get optional configurations | 322 | // Get optional configurations |
323 | maxSize = assetConfig.GetLong( "MaxSize", DefaultMaxSize ); | 323 | maxSize = assetConfig.GetLong( "MaxSize", DefaultMaxSize ); |
324 | maxCount = assetConfig.GetInt( "MaxCount", DefaultMaxCount ); | 324 | maxCount = assetConfig.GetInt( "MaxCount", DefaultMaxCount ); |
325 | expirationTime = | 325 | expirationTime = |
326 | TimeSpan.FromMinutes( assetConfig.GetInt( "ExpirationTime", (int) DefaultExpirationTime.TotalMinutes ) ); | 326 | TimeSpan.FromMinutes( assetConfig.GetInt( "ExpirationTime", (int) DefaultExpirationTime.TotalMinutes ) ); |
327 | 327 | ||
328 | // Debugging purposes only | 328 | // Debugging purposes only |
329 | m_debugEpoch = assetConfig.GetInt( "DebugEpoch", 0 ); | 329 | m_debugEpoch = assetConfig.GetInt( "DebugEpoch", 0 ); |
330 | } | 330 | } |
331 | 331 | ||
332 | Initialize( maxSize, maxCount, expirationTime ); | 332 | Initialize( maxSize, maxCount, expirationTime ); |
333 | } | 333 | } |
334 | 334 | ||
335 | /// <summary> | 335 | /// <summary> |
336 | /// Initialization post handling. | 336 | /// Initialization post handling. |
337 | /// </summary> | 337 | /// </summary> |
338 | /// <remarks> | 338 | /// <remarks> |
339 | /// <para> | 339 | /// <para> |
340 | /// Modules can use this to initialize connection with other modules. | 340 | /// Modules can use this to initialize connection with other modules. |
341 | /// </para> | 341 | /// </para> |
342 | /// </remarks> | 342 | /// </remarks> |
343 | public void PostInitialise() | 343 | public void PostInitialise() |
344 | { | 344 | { |
345 | } | 345 | } |
346 | 346 | ||
347 | /// <summary> | 347 | /// <summary> |
348 | /// Region has been loaded. | 348 | /// Region has been loaded. |
349 | /// </summary> | 349 | /// </summary> |
350 | /// <param name="scene"> | 350 | /// <param name="scene"> |
351 | /// Region's scene. | 351 | /// Region's scene. |
352 | /// </param> | 352 | /// </param> |
353 | /// <remarks> | 353 | /// <remarks> |
354 | /// <para> | 354 | /// <para> |
355 | /// This is needed for all module types. Modules will register | 355 | /// This is needed for all module types. Modules will register |
356 | /// Interfaces with scene in AddScene, and will also need a means | 356 | /// Interfaces with scene in AddScene, and will also need a means |
357 | /// to access interfaces registered by other modules. Without | 357 | /// to access interfaces registered by other modules. Without |
358 | /// this extra method, a module attempting to use another modules' | 358 | /// this extra method, a module attempting to use another modules' |
359 | /// interface would be successful only depending on load order, | 359 | /// interface would be successful only depending on load order, |
360 | /// which can't be depended upon, or modules would need to resort | 360 | /// which can't be depended upon, or modules would need to resort |
361 | /// to ugly kludges to attempt to request interfaces when needed | 361 | /// to ugly kludges to attempt to request interfaces when needed |
362 | /// and unnecessary caching logic repeated in all modules. | 362 | /// and unnecessary caching logic repeated in all modules. |
363 | /// The extra function stub is just that much cleaner. | 363 | /// The extra function stub is just that much cleaner. |
364 | /// </para> | 364 | /// </para> |
365 | /// </remarks> | 365 | /// </remarks> |
366 | public void RegionLoaded( Scene scene ) | 366 | public void RegionLoaded( Scene scene ) |
367 | { | 367 | { |
368 | } | 368 | } |
369 | 369 | ||
370 | /// <summary> | 370 | /// <summary> |
371 | /// Region is being removed. | 371 | /// Region is being removed. |
372 | /// </summary> | 372 | /// </summary> |
373 | /// <param name="scene"> | 373 | /// <param name="scene"> |
374 | /// Region scene that is being removed. | 374 | /// Region scene that is being removed. |
375 | /// </param> | 375 | /// </param> |
376 | public void RemoveRegion( Scene scene ) | 376 | public void RemoveRegion( Scene scene ) |
377 | { | 377 | { |
378 | } | 378 | } |
379 | 379 | ||
380 | #endregion | 380 | #endregion |
381 | } | 381 | } |
382 | } | 382 | } |