Browse Source

remove Cenome assets cache module. Thanks to all that worked on it. Memory cache does not work well with current Garbage collect (not even .net native one)

UbitUmarov 3 years ago
parent
commit
acea30aa74

+ 0 - 1870
OpenSim/Framework/CnmMemoryCache.cs

@@ -1,1870 +0,0 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the OpenSimulator Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace OpenSim.Framework
-{
-    /// <summary>
-    /// Cenome memory based cache to store key/value pairs (elements) limited time and/or limited size.
-    /// </summary>
-    /// <typeparam name="TKey">
-    /// The type of keys in the cache.
-    /// </typeparam>
-    /// <typeparam name="TValue">
-    /// The type of values in the dictionary.
-    /// </typeparam>
-    /// <remarks>
-    /// <para>
-    /// Cenome memory cache stores elements to hash table generations. When new element is being added to cache, and new size would exceed
-    /// maximal allowed size or maximal amount of allowed element count, then elements in oldest generation are deleted. Last access time
-    /// is also tracked in generation level - thus it is possible that some elements are staying in cache far beyond their expiration time.
-    /// If elements in older generations are accessed through <see cref="TryGetValue"/> method, they are moved to newest generation.
-    /// </para>
-    /// </remarks>
-    public class CnmMemoryCache<TKey, TValue> : ICnmCache<TKey, TValue>
-    {
-        /// <summary>
-        /// Default maximal count.
-        /// </summary>
-        /// <seealso cref="MaxCount"/>
-        public const int DefaultMaxCount = 4096;
-
-        /// <summary>
-        /// Default maximal size.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// 128MB = 128 * 1024^2 = 134 217 728 bytes.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="MaxSize"/>
-        public const long DefaultMaxSize = 134217728;
-
-        /// <summary>
-        /// How many operations between time checks.
-        /// </summary>
-        private const int DefaultOperationsBetweenTimeChecks = 40;
-
-        /// <summary>
-        /// Default expiration time.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// 30 minutes.
-        /// </para>
-        /// </remarks>
-        public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes(30.0);
-
-        /// <summary>
-        /// Minimal allowed expiration time.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// 5 minutes.
-        /// </para>
-        /// </remarks>
-        public static readonly TimeSpan MinExpirationTime = TimeSpan.FromSeconds(10.0);
-
-        /// <summary>
-        /// Comparer used to compare element keys.
-        /// </summary>
-        /// <remarks>
-        /// Comparer is initialized by constructor.
-        /// </remarks>
-        /// <seealso cref="CnmMemoryCache{TKey,TValue}"/>
-        public readonly IEqualityComparer<TKey> Comparer;
-
-        /// <summary>
-        /// Expiration time.
-        /// </summary>
-        private TimeSpan m_expirationTime = DefaultExpirationTime;
-
-        /// <summary>
-        /// Generation bucket count.
-        /// </summary>
-        private int m_generationBucketCount;
-
-        /// <summary>
-        /// Generation entry count.
-        /// </summary>
-        private int m_generationElementCount;
-
-        /// <summary>
-        /// Generation max size.
-        /// </summary>
-        private long m_generationMaxSize;
-
-        /// <summary>
-        /// Maximal allowed count of elements.
-        /// </summary>
-        private int m_maxCount;
-
-        /// <summary>
-        /// Maximal allowed total size of elements.
-        /// </summary>
-        private long m_maxElementSize;
-
-        /// <summary>
-        /// Maximal size.
-        /// </summary>
-        private long m_maxSize;
-
-        /// <summary>
-        /// New generation.
-        /// </summary>
-        private IGeneration m_newGeneration;
-
-        /// <summary>
-        /// Old generation.
-        /// </summary>
-        private IGeneration m_oldGeneration;
-
-        /// <summary>
-        /// Operations between time check.
-        /// </summary>
-        private int m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks;
-
-        /// <summary>
-        /// Synchronization root object, should always be private and exists always
-        /// </summary>
-        private readonly object m_syncRoot = new object();
-
-        /// <summary>
-        /// Version of cache.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Updated every time when cache has been changed (element removed, expired, added, replaced).
-        /// </para>
-        /// </remarks>
-        private int m_version;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
-        /// </summary>
-        public CnmMemoryCache()
-            : this(DefaultMaxSize)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
-        /// </summary>
-        /// <param name="maximalSize">
-        /// Maximal cache size.
-        /// </param>
-        public CnmMemoryCache(long maximalSize)
-            : this(maximalSize, DefaultMaxCount)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
-        /// </summary>
-        /// <param name="maximalSize">
-        /// Maximal cache size.
-        /// </param>
-        /// <param name="maximalCount">
-        /// Maximal element count.
-        /// </param>
-        public CnmMemoryCache(long maximalSize, int maximalCount)
-            : this(maximalSize, maximalCount, DefaultExpirationTime)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
-        /// </summary>
-        /// <param name="maximalSize">
-        /// Maximal cache size.
-        /// </param>
-        /// <param name="maximalCount">
-        /// Maximal element count.
-        /// </param>
-        /// <param name="expirationTime">
-        /// Elements expiration time.
-        /// </param>
-        public CnmMemoryCache(long maximalSize, int maximalCount, TimeSpan expirationTime)
-            : this(maximalSize, maximalCount, expirationTime, EqualityComparer<TKey>.Default)
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmMemoryCache{TKey,TValue}"/> class.
-        /// </summary>
-        /// <param name="maximalSize">
-        /// Maximal cache size.
-        /// </param>
-        /// <param name="maximalCount">
-        /// Maximal element count.
-        /// </param>
-        /// <param name="expirationTime">
-        /// Elements expiration time.
-        /// </param>
-        /// <param name="comparer">
-        /// Comparer used for comparing elements.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <see cref="comparer"/>is <see langword="null"/> reference.
-        /// </exception>
-        public CnmMemoryCache(long maximalSize,
-            int maximalCount,
-            TimeSpan expirationTime,
-            IEqualityComparer<TKey> comparer)
-        {
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            if (expirationTime < MinExpirationTime)
-                expirationTime = MinExpirationTime;
-            if (maximalCount < 8)
-                maximalCount = 8;
-            if (maximalSize < 8)
-                maximalSize = 8;
-            if (maximalCount > maximalSize)
-                maximalCount = (int) maximalSize;
-
-            Comparer = comparer;
-            m_expirationTime = expirationTime;
-            m_maxSize = maximalSize;
-            m_maxCount = maximalCount;
-
-            Initialize();
-        }
-
-        /// <summary>
-        /// Add element to new generation.
-        /// </summary>
-        /// <param name="bucketIndex">
-        /// The bucket index.
-        /// </param>
-        /// <param name="key">
-        /// The element's key.
-        /// </param>
-        /// <param name="value">
-        /// The element's value.
-        /// </param>
-        /// <param name="size">
-        /// The element's size.
-        /// </param>
-        protected virtual void AddToNewGeneration(int bucketIndex, TKey key, TValue value, long size)
-        {
-            // Add to newest generation
-            if (!m_newGeneration.Set(bucketIndex, key, value, size))
-            {
-                // Failed to add new generation
-                RecycleGenerations();
-                m_newGeneration.Set(bucketIndex, key, value, size);
-            }
-
-            m_version++;
-        }
-
-        /// <summary>
-        /// <para>
-        /// Get keys bucket index.
-        /// </para>
-        /// </summary>
-        /// <param name="key">
-        /// <para>
-        /// Key which bucket index is being retrieved.
-        /// </para>
-        /// </param>
-        /// <returns>
-        /// <para>
-        /// Bucket index.
-        /// </para>
-        /// </returns>
-        /// <remarks>
-        /// <para>
-        /// Method uses <see cref="Comparer"/> to calculate <see cref="key"/> hash code.
-        /// </para>
-        /// <para>
-        /// Bucket index is remainder when element key's hash value is divided by bucket count.
-        /// </para>
-        /// <para>
-        /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2.
-        /// </para>
-        /// </remarks>
-        protected virtual int GetBucketIndex(TKey key)
-        {
-            return (Comparer.GetHashCode(key) & 0x7FFFFFFF) % m_generationBucketCount;
-        }
-
-        /// <summary>
-        /// Purge generation from the cache.
-        /// </summary>
-        /// <param name="generation">
-        /// The generation that is purged.
-        /// </param>
-        protected virtual void PurgeGeneration(IGeneration generation)
-        {
-            generation.Clear();
-            m_version++;
-        }
-
-        /// <summary>
-        /// check expired.
-        /// </summary>
-        private void CheckExpired()
-        {
-            // Do this only one in every m_operationsBetweenTimeChecks
-            // Fetching time is using several millisecons - it is better not to do all time.
-            m_operationsBetweenTimeChecks--;
-            if (m_operationsBetweenTimeChecks <= 0)
-                PurgeExpired();
-        }
-
-        /// <summary>
-        /// Initialize cache.
-        /// </summary>
-        private void Initialize()
-        {
-            m_version++;
-
-            m_generationMaxSize = MaxSize / 2;
-            MaxElementSize = MaxSize / 8;
-            m_generationElementCount = MaxCount / 2;
-
-            // Buckets need to be prime number to get better spread of hash values
-            m_generationBucketCount = PrimeNumberHelper.GetPrime(m_generationElementCount);
-
-            m_newGeneration = new HashGeneration(this);
-            m_oldGeneration = new HashGeneration(this);
-            m_oldGeneration.MakeOld();
-        }
-
-        /// <summary>
-        /// Recycle generations.
-        /// </summary>
-        private void RecycleGenerations()
-        {
-            // Rotate old generation to new generation, new generation to old generation
-            IGeneration temp = m_newGeneration;
-            m_newGeneration = m_oldGeneration;
-            m_newGeneration.Clear();
-            m_oldGeneration = temp;
-            m_oldGeneration.MakeOld();
-        }
-
-        #region Nested type: Enumerator
-
-        /// <summary>
-        /// Key and value pair enumerator.
-        /// </summary>
-        private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
-        {
-            /// <summary>
-            /// Current enumerator.
-            /// </summary>
-            private int m_currentEnumerator = -1;
-
-            /// <summary>
-            /// Enumerators to different generations.
-            /// </summary>
-            private readonly IEnumerator<KeyValuePair<TKey, TValue>>[] m_generationEnumerators =
-                new IEnumerator<KeyValuePair<TKey, TValue>>[2];
-
-            /// <summary>
-            /// Initializes a new instance of the <see cref="Enumerator"/> class.
-            /// </summary>
-            /// <param name="cache">
-            /// The cache.
-            /// </param>
-            public Enumerator(CnmMemoryCache<TKey, TValue> cache)
-            {
-                m_generationEnumerators[ 0 ] = cache.m_newGeneration.GetEnumerator();
-                m_generationEnumerators[ 1 ] = cache.m_oldGeneration.GetEnumerator();
-            }
-
-            #region IEnumerator<KeyValuePair<TKey,TValue>> Members
-
-            /// <summary>
-            /// Gets the element in the collection at the current position of the enumerator.
-            /// </summary>
-            /// <returns>
-            /// The element in the collection at the current position of the enumerator.
-            /// </returns>
-            /// <exception cref="InvalidOperationException">
-            /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
-            /// </exception>
-            public KeyValuePair<TKey, TValue> Current
-            {
-                get
-                {
-                    if (m_currentEnumerator == -1 || m_currentEnumerator >= m_generationEnumerators.Length)
-                        throw new InvalidOperationException();
-
-                    return m_generationEnumerators[ m_currentEnumerator ].Current;
-                }
-            }
-
-            /// <summary>
-            /// Gets the current element in the collection.
-            /// </summary>
-            /// <returns>
-            /// The current element in the collection.
-            /// </returns>
-            /// <exception cref="T:System.InvalidOperationException">
-            /// The enumerator is positioned before the first element of the collection or after the last element.
-            /// </exception><filterpriority>2</filterpriority>
-            object IEnumerator.Current
-            {
-                get { return Current; }
-            }
-
-            /// <summary>
-            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-            /// </summary>
-            /// <filterpriority>2</filterpriority>
-            public void Dispose()
-            {
-            }
-
-            /// <summary>
-            /// Advances the enumerator to the next element of the collection.
-            /// </summary>
-            /// <returns>
-            /// <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.
-            /// </returns>
-            /// <exception cref="T:System.InvalidOperationException">
-            /// The collection was modified after the enumerator was created.
-            /// </exception>
-            /// <filterpriority>2</filterpriority>
-            public bool MoveNext()
-            {
-                if (m_currentEnumerator == -1)
-                    m_currentEnumerator = 0;
-
-                while (m_currentEnumerator < m_generationEnumerators.Length)
-                {
-                    if (m_generationEnumerators[ m_currentEnumerator ].MoveNext())
-                        return true;
-
-                    m_currentEnumerator++;
-                }
-
-                return false;
-            }
-
-            /// <summary>
-            /// Sets the enumerator to its initial position, which is before the first element in the collection.
-            /// </summary>
-            /// <exception cref="T:System.InvalidOperationException">
-            /// The collection was modified after the enumerator was created.
-            /// </exception>
-            /// <filterpriority>2</filterpriority>
-            public void Reset()
-            {
-                foreach (IEnumerator<KeyValuePair<TKey, TValue>> enumerator in m_generationEnumerators)
-                {
-                    enumerator.Reset();
-                }
-
-                m_currentEnumerator = -1;
-            }
-
-            #endregion
-        }
-
-        #endregion
-
-        #region Nested type: HashGeneration
-
-        /// <summary>
-        /// Hash generation class
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Current implementation is based to separated chaining with move-to-front heuristics. Hash generations have fixed
-        /// amount of buckets and it is never rehashed.
-        /// </para>
-        /// <para>
-        /// Read more about hash tables from <a href="http://en.wikipedia.org/wiki/Hash_table">Wiki article</a>.
-        /// </para>
-        /// </remarks>
-        /// <seealso href="http://en.wikipedia.org/wiki/Hash_table"/>
-        private class HashGeneration : IGeneration
-        {
-            /// <summary>
-            /// Value indicating whether generation was accessed since last time check.
-            /// </summary>
-            private bool m_accessedSinceLastTimeCheck;
-
-            /// <summary>
-            /// Index of first element's in element chain.
-            /// </summary>
-            /// <value>
-            /// -1 if there is no element in bucket; otherwise first element's index in the element chain.
-            /// </value>
-            /// <remarks>
-            /// Bucket index is remainder when element key's hash value is divided by bucket count.
-            /// For example: key's hash is 72, bucket count is 5, element's bucket index is 72 % 5 = 2.
-            /// </remarks>
-            private readonly int[] m_buckets;
-
-            /// <summary>
-            /// Cache object.
-            /// </summary>
-            private readonly CnmMemoryCache<TKey, TValue> m_cache;
-
-            /// <summary>
-            /// Generation's element array.
-            /// </summary>
-            /// <seealso cref="Element"/>
-            private readonly Element[] m_elements;
-
-            /// <summary>
-            /// Generation's expiration time.
-            /// </summary>
-            private DateTime m_expirationTime1;
-
-            /// <summary>
-            /// Index to first free element.
-            /// </summary>
-            private int m_firstFreeElement;
-
-            /// <summary>
-            /// Free element count.
-            /// </summary>
-            /// <remarks>
-            /// When generation is cleared or constructed, this is NOT set to element count.
-            /// This is only tracking elements that are removed and are currently free.
-            /// </remarks>
-            private int m_freeCount;
-
-            /// <summary>
-            /// Is this generation "new generation".
-            /// </summary>
-            private bool m_newGeneration;
-
-            /// <summary>
-            /// Next unused entry.
-            /// </summary>
-            private int m_nextUnusedElement;
-
-            /// <summary>
-            /// Size of data stored to generation.
-            /// </summary>
-            private long m_size;
-
-            /// <summary>
-            /// Initializes a new instance of the <see cref="HashGeneration"/> class.
-            /// </summary>
-            /// <param name="cache">
-            /// The cache.
-            /// </param>
-            public HashGeneration(CnmMemoryCache<TKey, TValue> cache)
-            {
-                m_cache = cache;
-                m_elements = new Element[m_cache.m_generationElementCount];
-                m_buckets = new int[m_cache.m_generationBucketCount];
-                Clear();
-            }
-
-            /// <summary>
-            /// Find element's index
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <param name="moveToFront">
-            /// Move element to front of elements.
-            /// </param>
-            /// <param name="previousIndex">
-            /// The previous element's index.
-            /// </param>
-            /// <returns>
-            /// Element's index, if found from the generation; -1 otherwise (if element is not found the generation).
-            /// </returns>
-            private int FindElementIndex(int bucketIndex, TKey key, bool moveToFront, out int previousIndex)
-            {
-                previousIndex = -1;
-                int elementIndex = m_buckets[ bucketIndex ];
-                while (elementIndex >= 0)
-                {
-                    if (m_cache.Comparer.Equals(key, m_elements[ elementIndex ].Key))
-                    {
-                        // Found match
-                        if (moveToFront && previousIndex >= 0)
-                        {
-                            // Move entry to front
-                            m_elements[ previousIndex ].Next = m_elements[ elementIndex ].Next;
-                            m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ];
-                            m_buckets[ bucketIndex ] = elementIndex;
-                            previousIndex = 0;
-                        }
-
-                        return elementIndex;
-                    }
-
-                    previousIndex = elementIndex;
-                    elementIndex = m_elements[ elementIndex ].Next;
-                }
-
-                return -1;
-            }
-
-            /// <summary>
-            /// Remove element front the generation.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The bucket index.
-            /// </param>
-            /// <param name="entryIndex">
-            /// The element index.
-            /// </param>
-            /// <param name="previousIndex">
-            /// The element's previous index.
-            /// </param>
-            private void RemoveElement(int bucketIndex, int entryIndex, int previousIndex)
-            {
-                if (previousIndex >= 0)
-                    m_elements[ previousIndex ].Next = m_elements[ entryIndex ].Next;
-                else
-                    m_buckets[ bucketIndex ] = m_elements[ entryIndex ].Next;
-
-                Size -= m_elements[ entryIndex ].Size;
-                m_elements[ entryIndex ].Value = default(TValue);
-                m_elements[ entryIndex ].Key = default(TKey);
-
-                // Add element to free elements list
-                m_elements[ entryIndex ].Next = m_firstFreeElement;
-                m_firstFreeElement = entryIndex;
-                m_freeCount++;
-            }
-
-            #region Nested type: Element
-
-            /// <summary>
-            /// Element that stores key, next element in chain, size and value.
-            /// </summary>
-            private struct Element
-            {
-                /// <summary>
-                /// Element's key.
-                /// </summary>
-                public TKey Key;
-
-                /// <summary>
-                /// Next element in chain.
-                /// </summary>
-                /// <remarks>
-                /// When element have value (something is stored to it), this is index of
-                /// next element with same bucket index. When element is free, this
-                /// is index of next element in free element's list.
-                /// </remarks>
-                public int Next;
-
-                /// <summary>
-                /// Size of element.
-                /// </summary>
-                /// <value>
-                /// 0 if element is free; otherwise larger than 0.
-                /// </value>
-                public long Size;
-
-                /// <summary>
-                /// Element's value.
-                /// </summary>
-                /// <remarks>
-                /// It is possible that this value is <see langword="null"/> even when element
-                /// have value - element's value is then <see langword="null"/> reference.
-                /// </remarks>
-                public TValue Value;
-
-                /// <summary>
-                /// Gets a value indicating whether element is free or have value.
-                /// </summary>
-                /// <value>
-                /// <see langword="true"/> when element is free; otherwise <see langword="false"/>.
-                /// </value>
-                public bool IsFree
-                {
-                    get { return Size == 0; }
-                }
-            }
-
-            #endregion
-
-            #region Nested type: Enumerator
-
-            /// <summary>
-            /// Key value pair enumerator for <see cref="HashGeneration"/> object.
-            /// </summary>
-            private class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
-            {
-                /// <summary>
-                /// Current element.
-                /// </summary>
-                private KeyValuePair<TKey, TValue> m_current;
-
-                /// <summary>
-                /// Current index.
-                /// </summary>
-                private int m_currentIndex;
-
-                /// <summary>
-                /// Generation that is being enumerated.
-                /// </summary>
-                private readonly HashGeneration m_generation;
-
-                /// <summary>
-                /// Cache version.
-                /// </summary>
-                /// <remarks>
-                /// When cache is change, version number is changed.
-                /// </remarks>
-                /// <seealso cref="CnmMemoryCache{TKey,TValue}.m_version"/>
-                private readonly int m_version;
-
-                /// <summary>
-                /// Initializes a new instance of the <see cref="Enumerator"/> class.
-                /// </summary>
-                /// <param name="generation">
-                /// The generation.
-                /// </param>
-                public Enumerator(HashGeneration generation)
-                {
-                    m_generation = generation;
-                    m_version = m_generation.m_cache.m_version;
-                }
-
-                #region IEnumerator<KeyValuePair<TKey,TValue>> Members
-
-                /// <summary>
-                /// Gets the element in the collection at the current position of the enumerator.
-                /// </summary>
-                /// <returns>
-                /// The element in the collection at the current position of the enumerator.
-                /// </returns>
-                /// <exception cref="InvalidOperationException">
-                /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
-                /// </exception>
-                public KeyValuePair<TKey, TValue> Current
-                {
-                    get
-                    {
-                        if (m_currentIndex == 0 || m_currentIndex >= m_generation.Count)
-                            throw new InvalidOperationException();
-
-                        return m_current;
-                    }
-                }
-
-                /// <summary>
-                /// Gets the current element in the collection.
-                /// </summary>
-                /// <returns>
-                /// The current element in the collection.
-                /// </returns>
-                /// <exception cref="InvalidOperationException">
-                /// The enumerator is positioned before the first element of the collection or after the last element.
-                /// </exception><filterpriority>2</filterpriority>
-                object IEnumerator.Current
-                {
-                    get { return Current; }
-                }
-
-                /// <summary>
-                /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-                /// </summary>
-                /// <filterpriority>2</filterpriority>
-                public void Dispose()
-                {
-                }
-
-                /// <summary>
-                /// Advances the enumerator to the next element of the collection.
-                /// </summary>
-                /// <returns>
-                /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
-                /// </returns>
-                /// <exception cref="InvalidOperationException">
-                /// The collection was modified after the enumerator was created.
-                /// </exception>
-                public bool MoveNext()
-                {
-                    if (m_version != m_generation.m_cache.m_version)
-                        throw new InvalidOperationException();
-
-                    while (m_currentIndex < m_generation.Count)
-                    {
-                        if (m_generation.m_elements[ m_currentIndex ].IsFree)
-                        {
-                            m_currentIndex++;
-                            continue;
-                        }
-
-                        m_current = new KeyValuePair<TKey, TValue>(m_generation.m_elements[ m_currentIndex ].Key,
-                            m_generation.m_elements[ m_currentIndex ].Value);
-                        m_currentIndex++;
-                        return true;
-                    }
-
-                    m_current = new KeyValuePair<TKey, TValue>();
-                    return false;
-                }
-
-                /// <summary>
-                /// Sets the enumerator to its initial position, which is before the first element in the collection.
-                /// </summary>
-                /// <exception cref="InvalidOperationException">
-                /// The collection was modified after the enumerator was created.
-                /// </exception>
-                /// <filterpriority>2</filterpriority>
-                public void Reset()
-                {
-                    if (m_version != m_generation.m_cache.m_version)
-                        throw new InvalidOperationException();
-
-                    m_currentIndex = 0;
-                }
-
-                #endregion
-            }
-
-            #endregion
-
-            #region IGeneration Members
-
-            /// <summary>
-            /// Gets or sets a value indicating whether generation was accessed since last time check.
-            /// </summary>
-            public bool AccessedSinceLastTimeCheck
-            {
-                get { return m_accessedSinceLastTimeCheck; }
-
-                set { m_accessedSinceLastTimeCheck = value; }
-            }
-
-            /// <summary>
-            /// Gets element count in generation.
-            /// </summary>
-            public int Count
-            {
-                get { return m_nextUnusedElement - m_freeCount; }
-            }
-
-            /// <summary>
-            /// Gets or sets generation's expiration time.
-            /// </summary>
-            public DateTime ExpirationTime
-            {
-                get { return m_expirationTime1; }
-
-                set { m_expirationTime1 = value; }
-            }
-
-            /// <summary>
-            /// Gets or sets size of data stored to generation.
-            /// </summary>
-            public long Size
-            {
-                get { return m_size; }
-
-                private set { m_size = value; }
-            }
-
-            /// <summary>
-            /// Clear all elements from the generation and make generation new again.
-            /// </summary>
-            /// <remarks>
-            /// When generation is new, it is allowed to add new elements to it and
-            /// <see cref="IGeneration.TryGetValue"/>doesn't remove elements from it.
-            /// </remarks>
-            /// <seealso cref="IGeneration.MakeOld"/>
-            public void Clear()
-            {
-                for (int i = m_buckets.Length - 1 ; i >= 0 ; i--)
-                {
-                    m_buckets[ i ] = -1;
-                }
-
-                Array.Clear(m_elements, 0, m_elements.Length);
-                Size = 0;
-                m_firstFreeElement = -1;
-                m_freeCount = 0;
-                m_nextUnusedElement = 0;
-                m_newGeneration = true;
-                ExpirationTime = DateTime.MaxValue;
-            }
-
-            /// <summary>
-            /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>.
-            /// </param>
-            /// <param name="key">
-            /// The key to locate in the <see cref="IGeneration"/>.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>;
-            /// otherwise <see langword="false"/>.
-            /// </returns>
-            public bool Contains(int bucketIndex, TKey key)
-            {
-                int previousIndex;
-                if (FindElementIndex(bucketIndex, key, true, out previousIndex) == -1)
-                    return false;
-
-                AccessedSinceLastTimeCheck = true;
-                return true;
-            }
-
-            /// <summary>
-            /// Returns an enumerator that iterates through the elements stored <see cref="HashGeneration"/>.
-            /// </summary>
-            /// <returns>
-            /// A <see cref="IEnumerator"/> that can be used to iterate through the <see cref="HashGeneration"/>.
-            /// </returns>
-            /// <filterpriority>1</filterpriority>
-            public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-            {
-                return new Enumerator(this);
-            }
-
-            /// <summary>
-            /// Make from generation old generation.
-            /// </summary>
-            /// <remarks>
-            /// When generation is old, <see cref="IGeneration.TryGetValue"/> hit removes element from the generation.
-            /// </remarks>
-            /// <seealso cref="IGeneration.Clear"/>
-            public void MakeOld()
-            {
-                m_newGeneration = false;
-            }
-
-            /// <summary>
-            /// Remove element associated with the key from the generation.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>.
-            /// </returns>
-            public bool Remove(int bucketIndex, TKey key)
-            {
-                int previousIndex;
-                int entryIndex = FindElementIndex(bucketIndex, key, false, out previousIndex);
-                if (entryIndex != -1)
-                {
-                    RemoveElement(bucketIndex, entryIndex, previousIndex);
-                    AccessedSinceLastTimeCheck = true;
-                    return true;
-                }
-
-                return false;
-            }
-
-            /// <summary>
-            /// Set or add element to generation.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <param name="value">
-            /// The element's value.
-            /// </param>
-            /// <param name="size">
-            /// The element's size.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>.
-            /// </returns>
-            /// <remarks>
-            /// <para>
-            /// If element was already existing in generation and new element size fits to collection limits,
-            /// then it's value is replaced with new one and size information is updated. If element didn't
-            /// exists in generation before, then generation must have empty space for a new element and
-            /// size must fit generation's limits, before element is added to generation.
-            /// </para>
-            /// </remarks>
-            public bool Set(int bucketIndex, TKey key, TValue value, long size)
-            {
-                Debug.Assert(m_newGeneration, "It is possible to insert new elements only to newest generation.");
-                Debug.Assert(size > 0, "New element size should be more than 0.");
-
-                int previousIndex;
-                int elementIndex = FindElementIndex(bucketIndex, key, true, out previousIndex);
-                if (elementIndex == -1)
-                {
-                    // New key
-                    if (Size + size > m_cache.m_generationMaxSize ||
-                        (m_nextUnusedElement == m_cache.m_generationElementCount && m_freeCount == 0))
-                    {
-                        // Generation is full
-                        return false;
-                    }
-
-                    // Increase size of generation
-                    Size += size;
-
-                    // Get first free entry and update free entry list
-                    if (m_firstFreeElement != -1)
-                    {
-                        // There was entry that was removed
-                        elementIndex = m_firstFreeElement;
-                        m_firstFreeElement = m_elements[ elementIndex ].Next;
-                        m_freeCount--;
-                    }
-                    else
-                    {
-                        // No entries removed so far - just take a last one
-                        elementIndex = m_nextUnusedElement;
-                        m_nextUnusedElement++;
-                    }
-
-                    Debug.Assert(m_elements[ elementIndex ].IsFree, "Allocated element is not free.");
-
-                    // Move new entry to front
-                    m_elements[ elementIndex ].Next = m_buckets[ bucketIndex ];
-                    m_buckets[ bucketIndex ] = elementIndex;
-
-                    // Set key and update count
-                    m_elements[ elementIndex ].Key = key;
-                }
-                else
-                {
-                    // Existing key
-                    if (Size - m_elements[ elementIndex ].Size + size > m_cache.m_generationMaxSize)
-                    {
-                        // Generation is full
-                        // Remove existing element, because generation is going to be recycled to
-                        // old generation and element is stored to new generation
-                        RemoveElement(bucketIndex, elementIndex, previousIndex);
-                        return false;
-                    }
-
-                    // Update generation's size
-                    Size = Size - m_elements[ elementIndex ].Size + size;
-                }
-
-                // Finally set value and size
-                m_elements[ elementIndex ].Value = value;
-                m_elements[ elementIndex ].Size = size;
-
-                // Success - key was inserterted to generation
-                AccessedSinceLastTimeCheck = true;
-                return true;
-            }
-
-            /// <summary>
-            /// Try to get element associated with key.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <param name="value">
-            /// The element's value.
-            /// </param>
-            /// <param name="size">
-            /// The element's size.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>.
-            /// </returns>
-            /// <remarks>
-            /// <para>
-            /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/>
-            /// are set to default value (default(TValue) and 0).
-            /// </para>
-            /// </remarks>
-            public bool TryGetValue(int bucketIndex, TKey key, out TValue value, out long size)
-            {
-                // Find entry index,
-                int previousIndex;
-                int elementIndex = FindElementIndex(bucketIndex, key, m_newGeneration, out previousIndex);
-                if (elementIndex == -1)
-                {
-                    value = default(TValue);
-                    size = 0;
-                    return false;
-                }
-
-                value = m_elements[ elementIndex ].Value;
-                size = m_elements[ elementIndex ].Size;
-
-                if (!m_newGeneration)
-                {
-                    // Old generation - remove element, because it is moved to new generation
-                    RemoveElement(bucketIndex, elementIndex, previousIndex);
-                }
-
-                AccessedSinceLastTimeCheck = true;
-                return true;
-            }
-
-            /// <summary>
-            /// Returns an enumerator that iterates through a collection.
-            /// </summary>
-            /// <returns>
-            /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
-            /// </returns>
-            /// <filterpriority>2</filterpriority>
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return GetEnumerator();
-            }
-
-            #endregion
-        }
-
-        #endregion
-
-        #region Nested type: IGeneration
-
-        /// <summary>
-        /// Cache element generation interface
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Generation can hold limited count of elements and limited size of data.
-        /// </para>
-        /// <para>
-        /// There are two kind generations: "new generation" and "old generation(s)". All new elements
-        /// are added to "new generation".
-        /// </para>
-        /// </remarks>
-        protected interface IGeneration : IEnumerable<KeyValuePair<TKey, TValue>>
-        {
-            /// <summary>
-            /// Gets or sets a value indicating whether generation was accessed since last time check.
-            /// </summary>
-            bool AccessedSinceLastTimeCheck { get; set; }
-
-            /// <summary>
-            /// Gets element count in generation.
-            /// </summary>
-            int Count { get; }
-
-            /// <summary>
-            /// Gets or sets generation's expiration time.
-            /// </summary>
-            DateTime ExpirationTime { get; set; }
-
-            /// <summary>
-            /// Gets size of data stored to generation.
-            /// </summary>
-            long Size { get; }
-
-            /// <summary>
-            /// Clear all elements from the generation and make generation new again.
-            /// </summary>
-            /// <remarks>
-            /// When generation is new, it is allowed to add new elements to it and
-            /// <see cref="TryGetValue"/>doesn't remove elements from it.
-            /// </remarks>
-            /// <seealso cref="MakeOld"/>
-            void Clear();
-
-            /// <summary>
-            /// Determines whether the <see cref="IGeneration"/> contains an element with the specific key.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The bucket index for the <see cref="key"/> to locate in <see cref="IGeneration"/>.
-            /// </param>
-            /// <param name="key">
-            /// The key to locate in the <see cref="IGeneration"/>.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>if the <see cref="IGeneration"/> contains an element with the <see cref="key"/>;
-            /// otherwise <see langword="false"/>.
-            /// </returns>
-            bool Contains(int bucketIndex, TKey key);
-
-            /// <summary>
-            /// Make from generation old generation.
-            /// </summary>
-            /// <remarks>
-            /// When generation is old, <see cref="TryGetValue"/> hit removes element from the generation.
-            /// </remarks>
-            /// <seealso cref="Clear"/>
-            void MakeOld();
-
-            /// <summary>
-            /// Remove element associated with the key from the generation.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if remove was successful; otherwise <see langword="false"/>.
-            /// </returns>
-            bool Remove(int bucketIndex, TKey key);
-
-            /// <summary>
-            /// Set or add element to generation.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <param name="value">
-            /// The element's value.
-            /// </param>
-            /// <param name="size">
-            /// The element's size.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if setting or adding was successful; otherwise <see langword="false"/>.
-            /// </returns>
-            /// <remarks>
-            /// <para>
-            /// If element was already existing in generation and new element size fits to collection limits,
-            /// then it's value is replaced with new one and size information is updated. If element didn't
-            /// exists in generation before, then generation must have empty space for a new element and
-            /// size must fit generation's limits, before element is added to generation.
-            /// </para>
-            /// </remarks>
-            bool Set(int bucketIndex, TKey key, TValue value, long size);
-
-            /// <summary>
-            /// Try to get element associated with key.
-            /// </summary>
-            /// <param name="bucketIndex">
-            /// The element's bucket index.
-            /// </param>
-            /// <param name="key">
-            /// The element's key.
-            /// </param>
-            /// <param name="value">
-            /// The element's value.
-            /// </param>
-            /// <param name="size">
-            /// The element's size.
-            /// </param>
-            /// <returns>
-            /// <see langword="true"/>, if element was successful retrieved; otherwise <see langword="false"/>.
-            /// </returns>
-            /// <remarks>
-            /// <para>
-            /// If element is not found from generation then <paramref name="value"/> and <paramref name="size"/>
-            /// are set to default value (default(TValue) and 0).
-            /// </para>
-            /// </remarks>
-            bool TryGetValue(int bucketIndex, TKey key, out TValue value, out long size);
-        }
-
-        #endregion
-
-        #region ICnmCache<TKey,TValue> Members
-
-        /// <summary>
-        /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public int Count
-        {
-            get { return m_newGeneration.Count + m_oldGeneration.Count; }
-        }
-
-        /// <summary>
-        /// Gets or sets elements expiration time.
-        /// </summary>
-        /// <value>
-        /// Elements expiration time.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is
-        /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
-        /// 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"/>.
-        /// </para>
-        /// <para>
-        /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired.
-        /// </para>
-        /// <para>
-        /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        public TimeSpan ExpirationTime
-        {
-            get { return m_expirationTime; }
-
-            set
-            {
-                if (value < MinExpirationTime)
-                    value = MinExpirationTime;
-
-                if (m_expirationTime == value)
-                    return;
-
-                m_newGeneration.ExpirationTime = (m_newGeneration.ExpirationTime - m_expirationTime) + value;
-                m_oldGeneration.ExpirationTime = (m_oldGeneration.ExpirationTime - m_expirationTime) + value;
-                m_expirationTime = value;
-
-                PurgeExpired();
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public bool IsCountLimited
-        {
-            get { return true; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public bool IsSizeLimited
-        {
-            get { return true; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
-        /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
-        /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        public bool IsSynchronized
-        {
-            get { return false; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/>
-        /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from
-        /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
-        /// stay longer in cache.
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        public bool IsTimeLimited
-        {
-            get { return ExpirationTime != TimeSpan.MaxValue; }
-        }
-
-        /// <summary>
-        /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
-        /// otherwise maximal allowed count of elements.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        public int MaxCount
-        {
-            get { return m_maxCount; }
-
-            set
-            {
-                if (value < 8)
-                    value = 8;
-                if (m_maxCount == value)
-                    return;
-
-                m_maxCount = value;
-                Initialize();
-            }
-        }
-
-        /// <summary>
-        /// <para>Gets maximal allowed element size.</para>
-        /// </summary>
-        /// <value>
-        /// Maximal allowed element size.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        public long MaxElementSize
-        {
-            get { return m_maxElementSize; }
-
-            private set { m_maxElementSize = value; }
-        }
-
-        /// <summary>
-        /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        public long MaxSize
-        {
-            get { return m_maxSize; }
-
-            set
-            {
-                if (value < 8)
-                    value = 8;
-                if (m_maxSize == value)
-                    return;
-
-                m_maxSize = value;
-                Initialize();
-            }
-        }
-
-        /// <summary>
-        /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally bytes, but can be any suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        public long Size
-        {
-            get { return m_newGeneration.Size + m_oldGeneration.Size; }
-        }
-
-        /// <summary>
-        /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
-        /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        public object SyncRoot
-        {
-            get { return m_syncRoot; }
-        }
-
-        /// <summary>
-        /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void Clear()
-        {
-            m_newGeneration.Clear();
-            m_oldGeneration.Clear();
-            m_oldGeneration.MakeOld();
-            m_version++;
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the elements stored to <see cref="CnmMemoryCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
-        /// </returns>
-        /// <filterpriority>1</filterpriority>
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            return new Enumerator(this);
-        }
-
-        /// <summary>
-        /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
-        /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        public void PurgeExpired()
-        {
-            m_operationsBetweenTimeChecks = DefaultOperationsBetweenTimeChecks;
-
-            if (!IsTimeLimited)
-                return;
-
-            DateTime now = DateTime.Now;
-            if (m_newGeneration.AccessedSinceLastTimeCheck)
-            {
-                // New generation has been accessed since last check
-                // Update it's expiration time.
-                m_newGeneration.ExpirationTime = now + ExpirationTime;
-                m_newGeneration.AccessedSinceLastTimeCheck = false;
-            }
-            else if (m_newGeneration.ExpirationTime < now)
-            {
-                // New generation has been expired.
-                // --> also old generation must be expired.
-                PurgeGeneration(m_newGeneration);
-                PurgeGeneration(m_oldGeneration);
-                return;
-            }
-
-            if (m_oldGeneration.ExpirationTime < now)
-                PurgeGeneration(m_oldGeneration);
-        }
-
-        /// <summary>
-        /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void Remove(TKey key)
-        {
-            if (key == null)
-                throw new ArgumentNullException("key");
-
-            int bucketIndex = GetBucketIndex(key);
-            if (!m_newGeneration.Remove(bucketIndex, key))
-            {
-                if (!m_oldGeneration.Remove(bucketIndex, key))
-                {
-                    CheckExpired();
-                    return;
-                }
-            }
-
-            CheckExpired();
-            m_version++;
-        }
-
-        /// <summary>
-        /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="keys">
-        /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="keys"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void RemoveRange(IEnumerable<TKey> keys)
-        {
-            if (keys == null)
-                throw new ArgumentNullException("keys");
-
-            foreach (TKey key in keys)
-            {
-                if (key == null)
-                    continue;
-
-                int bucketIndex = GetBucketIndex(key);
-                if (!m_newGeneration.Remove(bucketIndex, key))
-                    m_oldGeneration.Remove(bucketIndex, key);
-            }
-
-            CheckExpired();
-            m_version++;
-        }
-
-        /// <summary>
-        /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The object used as the key of the element. Can't be <see langword="null"/> reference.
-        /// </param>
-        /// <param name="value">
-        /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
-        /// </param>
-        /// <param name="size">
-        /// The element's size. Normally bytes, but can be any suitable unit of measure.
-        /// </param>
-        /// <returns>
-        /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
-        /// otherwise <see langword="false"/>.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <exception cref="ArgumentOutOfRangeException">
-        /// The element's <paramref name="size"/> is less than 0.
-        /// </exception>
-        /// <remarks>
-        /// <para>
-        /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
-        /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public bool Set(TKey key, TValue value, long size)
-        {
-            if (key == null)
-                throw new ArgumentNullException("key");
-
-            if (size < 0)
-                throw new ArgumentOutOfRangeException("size", size, "Value's size can't be less than 0.");
-
-            if (size > MaxElementSize)
-            {
-                // Entry size is too big to fit cache - ignore it
-                Remove(key);
-                return false;
-            }
-
-            if (size == 0)
-                size = 1;
-
-            int bucketIndex = GetBucketIndex(key);
-            m_oldGeneration.Remove(bucketIndex, key);
-            AddToNewGeneration(bucketIndex, key, value, size);
-            CheckExpired();
-
-            return true;
-        }
-
-        /// <summary>
-        /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
-        /// </summary>
-        /// <returns>
-        /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
-        /// the specified key; otherwise, <see langword="false"/>.
-        /// </returns>
-        /// <param name="key">
-        /// The key whose <paramref name="value"/> to get.
-        /// </param>
-        /// <param name="value">
-        /// When this method returns, the value associated with the specified <paramref name="key"/>,
-        /// if the <paramref name="key"/> is found; otherwise, the
-        /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            if (key == null)
-                throw new ArgumentNullException("key");
-
-            int bucketIndex = GetBucketIndex(key);
-            long size;
-            if (m_newGeneration.TryGetValue(bucketIndex, key, out value, out size))
-            {
-                CheckExpired();
-                return true;
-            }
-
-            if (m_oldGeneration.TryGetValue(bucketIndex, key, out value, out size))
-            {
-                // Move element to new generation
-                AddToNewGeneration(bucketIndex, key, value, size);
-                CheckExpired();
-                return true;
-            }
-
-            CheckExpired();
-            return false;
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through a collection.
-        /// </summary>
-        /// <returns>
-        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
-        /// </returns>
-        /// <filterpriority>2</filterpriority>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
-
-        #endregion
-    }
-}

+ 0 - 747
OpenSim/Framework/CnmSynchronizedCache.cs

@@ -1,747 +0,0 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the OpenSimulator Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace OpenSim.Framework
-{
-    /// <summary>
-    /// Synchronized Cenome cache wrapper.
-    /// </summary>
-    /// <typeparam name="TKey">
-    /// The type of keys in the cache.
-    /// </typeparam>
-    /// <typeparam name="TValue">
-    /// The type of values in the cache.
-    /// </typeparam>
-    /// <remarks>
-    /// <para>
-    /// Enumerator will block other threads, until enumerator's <see cref="IDisposable.Dispose"/> method is called.
-    /// "foreach" statement is automatically calling it.
-    /// </para>
-    /// </remarks>
-    public class CnmSynchronizedCache<TKey, TValue> : ICnmCache<TKey, TValue>
-    {
-        /// <summary>
-        /// The cache object.
-        /// </summary>
-        private readonly ICnmCache<TKey, TValue> m_cache;
-
-        /// <summary>
-        /// Synchronization root.
-        /// </summary>
-        private readonly object m_syncRoot;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class.
-        /// Initializes a new instance of the <see cref="CnmSynchronizedCache{TKey,TValue}"/> class.
-        /// </summary>
-        /// <param name="cache">
-        /// The cache.
-        /// </param>
-        private CnmSynchronizedCache(ICnmCache<TKey, TValue> cache)
-        {
-            m_cache = cache;
-            m_syncRoot = m_cache.SyncRoot;
-        }
-
-        /// <summary>
-        /// Returns a <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe).
-        /// </summary>
-        /// <param name="cache">
-        /// The <see cref="ICnmCache{TKey,TValue}"/> to synchronize.
-        /// </param>
-        /// <returns>
-        /// A <see cref="ICnmCache{TKey,TValue}"/> wrapper that is synchronized (thread safe).
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="cache"/>is null.
-        /// </exception>
-        public static ICnmCache<TKey, TValue> Synchronized(ICnmCache<TKey, TValue> cache)
-        {
-            if (cache == null)
-                throw new ArgumentNullException("cache");
-            return cache.IsSynchronized ? cache : new CnmSynchronizedCache<TKey, TValue>(cache);
-        }
-
-        #region Nested type: SynchronizedEnumerator
-
-        /// <summary>
-        /// Synchronized enumerator.
-        /// </summary>
-        private class SynchronizedEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>
-        {
-            /// <summary>
-            /// Enumerator that is being synchronized.
-            /// </summary>
-            private readonly IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator;
-
-            /// <summary>
-            /// Synchronization root.
-            /// </summary>
-            private object m_syncRoot;
-
-            /// <summary>
-            /// Initializes a new instance of the <see cref="SynchronizedEnumerator"/> class.
-            /// </summary>
-            /// <param name="enumerator">
-            /// The enumerator that is being synchronized.
-            /// </param>
-            /// <param name="syncRoot">
-            /// The sync root.
-            /// </param>
-            public SynchronizedEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator, object syncRoot)
-            {
-                m_syncRoot = syncRoot;
-                m_enumerator = enumerator;
-                Monitor.Enter(m_syncRoot);
-            }
-
-            /// <summary>
-            /// Finalizes an instance of the <see cref="SynchronizedEnumerator"/> class.
-            /// </summary>
-            ~SynchronizedEnumerator()
-            {
-                Dispose();
-            }
-
-            #region IEnumerator<KeyValuePair<TKey,TValue>> Members
-
-            /// <summary>
-            /// Gets the element in the collection at the current position of the enumerator.
-            /// </summary>
-            /// <returns>
-            /// The element in the collection at the current position of the enumerator.
-            /// </returns>
-            /// <exception cref="InvalidOperationException">
-            /// The enumerator has reach end of collection or <see cref="MoveNext"/> is not called.
-            /// </exception>
-            public KeyValuePair<TKey, TValue> Current
-            {
-                get { return m_enumerator.Current; }
-            }
-
-            /// <summary>
-            /// Gets the current element in the collection.
-            /// </summary>
-            /// <returns>
-            /// The current element in the collection.
-            /// </returns>
-            /// <exception cref="InvalidOperationException">
-            /// The enumerator is positioned before the first element of the collection or after the last element.
-            /// </exception><filterpriority>2</filterpriority>
-            object IEnumerator.Current
-            {
-                get { return Current; }
-            }
-
-            /// <summary>
-            /// Releases synchronization lock.
-            /// </summary>
-            public void Dispose()
-            {
-                if (m_syncRoot != null)
-                {
-                    Monitor.Exit(m_syncRoot);
-                    m_syncRoot = null;
-                }
-
-                m_enumerator.Dispose();
-                GC.SuppressFinalize(this);
-            }
-
-            /// <summary>
-            /// Advances the enumerator to the next element of the collection.
-            /// </summary>
-            /// <returns>
-            /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
-            /// </returns>
-            /// <exception cref="InvalidOperationException">
-            /// The collection was modified after the enumerator was created.
-            /// </exception>
-            public bool MoveNext()
-            {
-                return m_enumerator.MoveNext();
-            }
-
-            /// <summary>
-            /// Sets the enumerator to its initial position, which is before the first element in the collection.
-            /// </summary>
-            /// <exception cref="InvalidOperationException">
-            /// The collection was modified after the enumerator was created.
-            /// </exception>
-            public void Reset()
-            {
-                m_enumerator.Reset();
-            }
-
-            #endregion
-        }
-
-        #endregion
-
-        #region ICnmCache<TKey,TValue> Members
-
-        /// <summary>
-        /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public int Count
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.Count;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets elements expiration time.
-        /// </summary>
-        /// <value>
-        /// Elements expiration time.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// and it is not accessed through <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> method or element's value is
-        /// not replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method, then it is automatically removed from the
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
-        /// 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"/>.
-        /// </para>
-        /// <para>
-        /// It is also possible that element stays in cache longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Calling <see cref="ICnmCache{TKey,TValue}.PurgeExpired"/> try to remove all elements that are expired.
-        /// </para>
-        /// <para>
-        /// To disable time limit in cache, set <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        public TimeSpan ExpirationTime
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.ExpirationTime;
-                }
-            }
-
-            set
-            {
-                lock (m_syncRoot)
-                {
-                    m_cache.ExpirationTime = value;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Count"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxCount"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public bool IsCountLimited
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.IsCountLimited;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        public bool IsSizeLimited
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.IsSizeLimited;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
-        /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
-        /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.SyncRoot"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        public bool IsSynchronized
-        {
-            get { return true; }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="ICnmCache{TKey,TValue}.Set"/>
-        /// or <see cref="ICnmCache{TKey,TValue}.TryGetValue"/> methods in <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> , then element is automatically removed from
-        /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
-        /// stay longer in cache.
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        public bool IsTimeLimited
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.IsTimeLimited;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
-        /// otherwise maximal allowed count of elements.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        public int MaxCount
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.MaxCount;
-                }
-            }
-
-            set
-            {
-                lock (m_syncRoot)
-                {
-                    m_cache.MaxCount = value;
-                }
-            }
-        }
-
-        /// <summary>
-        /// <para>Gets maximal allowed element size.</para>
-        /// </summary>
-        /// <value>
-        /// Maximal allowed element size.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// If element's size is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        public long MaxElementSize
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.MaxElementSize;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Size"/>
-        public long MaxSize
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.MaxSize;
-                }
-            }
-
-            set
-            {
-                lock (m_syncRoot)
-                {
-                    m_cache.MaxSize = value;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally bytes, but can be any suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// Element's size is given when element is added or replaced by <see cref="ICnmCache{TKey,TValue}.Set"/> method.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxElementSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.MaxSize"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        public long Size
-        {
-            get
-            {
-                lock (m_syncRoot)
-                {
-                    return m_cache.Size;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
-        /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSynchronized"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        public object SyncRoot
-        {
-            get { return m_syncRoot; }
-        }
-
-        /// <summary>
-        /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void Clear()
-        {
-            lock (m_syncRoot)
-            {
-                m_cache.Clear();
-            }
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
-        /// </returns>
-        /// <filterpriority>1</filterpriority>
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            lock (m_syncRoot)
-            {
-                return new SynchronizedEnumerator(m_cache.GetEnumerator(), m_syncRoot);
-            }
-        }
-
-        /// <summary>
-        /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Element becomes expired when last access time to it has been longer time than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
-        /// may stay longer than <see cref="ICnmCache{TKey,TValue}.ExpirationTime"/> in the cache.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsTimeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.ExpirationTime"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        public void PurgeExpired()
-        {
-            lock (m_syncRoot)
-            {
-                m_cache.PurgeExpired();
-            }
-        }
-
-        /// <summary>
-        /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void Remove(TKey key)
-        {
-            lock (m_syncRoot)
-            {
-                m_cache.Remove(key);
-            }
-        }
-
-        /// <summary>
-        /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="keys">
-        /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="keys"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public void RemoveRange(IEnumerable<TKey> keys)
-        {
-            lock (m_syncRoot)
-            {
-                m_cache.RemoveRange(keys);
-            }
-        }
-
-        /// <summary>
-        /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The object used as the key of the element. Can't be <see langword="null"/> reference.
-        /// </param>
-        /// <param name="value">
-        /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
-        /// </param>
-        /// <param name="size">
-        /// The element's size. Normally bytes, but can be any suitable unit of measure.
-        /// </param>
-        /// <returns>
-        /// <see langword="true"/>if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
-        /// otherwise <see langword="false"/>.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <exception cref="ArgumentOutOfRangeException">
-        /// The element's <paramref name="size"/> is less than 0.
-        /// </exception>
-        /// <remarks>
-        /// <para>
-        /// If element's <paramref name="size"/> is larger than <see cref="ICnmCache{TKey,TValue}.MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
-        /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsSizeLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.IsCountLimited"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.TryGetValue"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public bool Set(TKey key, TValue value, long size)
-        {
-            lock (m_syncRoot)
-            {
-                return m_cache.Set(key, value, size);
-            }
-        }
-
-        /// <summary>
-        /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
-        /// </summary>
-        /// <returns>
-        /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
-        /// the specified key; otherwise, <see langword="false"/>.
-        /// </returns>
-        /// <param name="key">
-        /// The key whose <paramref name="value"/> to get.
-        /// </param>
-        /// <param name="value">
-        /// When this method returns, the value associated with the specified <paramref name="key"/>,
-        /// if the <paramref name="key"/> is found; otherwise, the
-        /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Set"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Remove"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.RemoveRange"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.Clear"/>
-        /// <seealso cref="ICnmCache{TKey,TValue}.PurgeExpired"/>
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            lock (m_syncRoot)
-            {
-                return m_cache.TryGetValue(key, out value);
-            }
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <returns>
-        /// A <see cref="IEnumerator"/> that can be used to iterate through the collection.
-        /// </returns>
-        /// <filterpriority>1</filterpriority>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
-
-        #endregion
-    }
-}

+ 0 - 441
OpenSim/Framework/ICnmCache.cs

@@ -1,441 +0,0 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the OpenSimulator Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Collections.Generic;
-
-namespace OpenSim.Framework
-{
-    /// <summary>
-    /// Represent generic cache to store key/value pairs (elements) limited by time, size and count of elements.
-    /// </summary>
-    /// <typeparam name="TKey">
-    /// The type of keys in the cache.
-    /// </typeparam>
-    /// <typeparam name="TValue">
-    /// The type of values in the cache.
-    /// </typeparam>
-    /// <remarks>
-    /// <para>
-    /// Cache store limitations:
-    /// </para>
-    /// <list type="table">
-    /// <listheader>
-    /// <term>Limitation</term>
-    /// <description>Description</description>
-    /// </listheader>
-    /// <item>
-    /// <term>Time</term>
-    /// <description>
-    /// Element that is not accessed through <see cref="TryGetValue"/> or <see cref="Set"/> in last <see cref="ExpirationTime"/> are
-    /// removed from the cache automatically. Depending on implementation of the cache some of elements may stay longer in cache.
-    /// <see cref="IsTimeLimited"/> returns <see langword="true"/>, if cache is limited by time.
-    /// </description>
-    /// </item>
-    /// <item>
-    /// <term>Count</term>
-    /// <description>
-    /// When adding an new element to cache that already have <see cref="MaxCount"/> of elements, cache will remove less recently
-    /// used element(s) from the cache, until element fits to cache.
-    /// <see cref="IsCountLimited"/> returns <see langword="true"/>, if cache is limiting element count.
-    /// </description>
-    /// </item>
-    /// <item>
-    /// <term>Size</term>
-    /// <description>
-    /// <description>
-    /// When adding an new element to cache that already have <see cref="MaxSize"/> of elements, cache will remove less recently
-    /// used element(s) from the cache, until element fits to cache.
-    /// <see cref="IsSizeLimited"/> returns <see langword="true"/>, if cache is limiting total size of elements.
-    /// Normally size is bytes used by element in the cache. But it can be any other suitable unit of measure.
-    /// </description>
-    /// </description>
-    /// </item>
-    /// </list>
-    /// </remarks>
-    public interface ICnmCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
-    {
-        /// <summary>
-        /// Gets current count of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="MaxCount"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="IsTimeLimited"/>
-        int Count { get; }
-
-        /// <summary>
-        /// Gets or sets elements expiration time.
-        /// </summary>
-        /// <value>
-        /// Elements expiration time.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When element has been stored in <see cref="ICnmCache{TKey,TValue}"/> longer than <see cref="ExpirationTime"/>
-        /// and it is not accessed through <see cref="TryGetValue"/> method or element's value is
-        /// not replaced by <see cref="Set"/> method, then it is automatically removed from the
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// It is possible that <see cref="ICnmCache{TKey,TValue}"/> implementation removes element before it's expiration time,
-        /// because total size or count of elements stored to cache is larger than <see cref="MaxSize"/> or <see cref="MaxCount"/>.
-        /// </para>
-        /// <para>
-        /// It is also possible that element stays in cache longer than <see cref="ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Calling <see cref="PurgeExpired"/> try to remove all elements that are expired.
-        /// </para>
-        /// <para>
-        /// To disable time limit in cache, set <see cref="ExpirationTime"/> to <see cref="DateTime.MaxValue"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="IsTimeLimited"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="PurgeExpired"/>
-        /// <seealso cref="Count"/>
-        /// <seealso cref="MaxCount"/>
-        /// <seealso cref="MaxSize"/>
-        /// <seealso cref="Size"/>
-        TimeSpan ExpirationTime { get; set; }
-
-        /// <summary>
-        /// Gets a value indicating whether or not access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe).
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if access to the <see cref="ICnmCache{TKey,TValue}"/> is synchronized (thread safe);
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/> object, use
-        /// <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> in <see cref="CnmSynchronizedCache{TKey,TValue}"/> class
-        /// to retrieve synchronized wrapper for <see cref="ICnmCache{TKey,TValue}"/> object.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="SyncRoot"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        bool IsSynchronized { get; }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting count of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> count of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="Count"/>
-        /// <seealso cref="MaxCount"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="IsTimeLimited"/>
-        bool IsCountLimited { get; }
-
-        /// <summary>
-        /// Gets a value indicating whether <see cref="ICnmCache{TKey,TValue}"/> is limiting size of elements.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> total size of elements is limited;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="MaxElementSize"/>
-        /// <seealso cref="Size"/>
-        /// <seealso cref="MaxSize"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="IsTimeLimited"/>
-        bool IsSizeLimited { get; }
-
-        /// <summary>
-        /// Gets a value indicating whether elements stored to <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time.
-        /// </summary>
-        /// <value>
-        /// <see langword="true"/> if the <see cref="ICnmCache{TKey,TValue}"/> has a fixed total size of elements;
-        /// otherwise, <see langword="false"/>.
-        /// </value>
-        /// <remarks>
-        /// If <see cref="ICnmCache{TKey,TValue}"/> have limited inactivity time and element is not accessed through <see cref="Set"/>
-        /// or <see cref="TryGetValue"/> methods in <see cref="ExpirationTime"/> , then element is automatically removed from
-        /// the cache. Depending on implementation of the <see cref="ICnmCache{TKey,TValue}"/>, some of the elements may
-        /// stay longer in cache.
-        /// </remarks>
-        /// <seealso cref="ExpirationTime"/>
-        /// <seealso cref="PurgeExpired"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="IsSizeLimited"/>
-        bool IsTimeLimited { get; }
-
-        /// <summary>
-        /// Gets or sets maximal allowed count of elements that can be stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// <see cref="int.MaxValue"/>, if <see cref="ICnmCache{TKey,TValue}"/> is not limited by count of elements;
-        /// otherwise maximal allowed count of elements.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        int MaxCount { get; set; }
-
-        /// <summary>
-        /// <para>Gets maximal allowed element size.</para>
-        /// </summary>
-        /// <value>
-        /// Maximal allowed element size.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// If element's size is larger than <see cref="MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="Size"/>
-        /// <seealso cref="MaxSize"/>
-        long MaxElementSize { get; }
-
-        /// <summary>
-        /// Gets or sets maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Maximal allowed total size for elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally size is total bytes used by elements in the cache. But it can be any other suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <exception cref="ArgumentOutOfRangeException">value is less than 0.</exception>
-        /// <seealso cref="MaxElementSize"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="Size"/>
-        long MaxSize { get; set; }
-
-        /// <summary>
-        /// Gets total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// Total size of elements stored to <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// Normally bytes, but can be any suitable unit of measure.
-        /// </para>
-        /// <para>
-        /// Element's size is given when element is added or replaced by <see cref="Set"/> method.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/> will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="MaxElementSize"/>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="MaxSize"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="ExpirationTime"/>
-        long Size { get; }
-
-        /// <summary>
-        /// Gets an object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <value>
-        /// An object that can be used to synchronize access to the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// To get synchronized (thread safe) access to <see cref="ICnmCache{TKey,TValue}"/>, use <see cref="CnmSynchronizedCache{TKey,TValue}"/>
-        /// method <see cref="CnmSynchronizedCache{TKey,TValue}.Synchronized"/> to retrieve synchronized wrapper interface to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="IsSynchronized"/>
-        /// <seealso cref="CnmSynchronizedCache{TKey,TValue}"/>
-        object SyncRoot { get; }
-
-        /// <summary>
-        /// Removes all elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="Remove"/>
-        /// <seealso cref="RemoveRange"/>
-        /// <seealso cref="TryGetValue"/>
-        /// <seealso cref="PurgeExpired"/>
-        void Clear();
-
-        /// <summary>
-        /// Purge expired elements from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Element becomes expired when last access time to it has been longer time than <see cref="ExpirationTime"/>.
-        /// </para>
-        /// <para>
-        /// Depending on <see cref="ICnmCache{TKey,TValue}"/> implementation, some of expired elements
-        /// may stay longer than <see cref="ExpirationTime"/> in the cache.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="IsTimeLimited"/>
-        /// <seealso cref="ExpirationTime"/>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="Remove"/>
-        /// <seealso cref="RemoveRange"/>
-        /// <seealso cref="TryGetValue"/>
-        /// <seealso cref="Clear"/>
-        void PurgeExpired();
-
-        /// <summary>
-        /// Removes element associated with <paramref name="key"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The key that is associated with element to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/> is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="RemoveRange"/>
-        /// <seealso cref="TryGetValue"/>
-        /// <seealso cref="Clear"/>
-        /// <seealso cref="PurgeExpired"/>
-        void Remove(TKey key);
-
-        /// <summary>
-        /// Removes elements that are associated with one of <paramref name="keys"/> from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="keys">
-        /// The keys that are associated with elements to remove from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="keys"/> is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="Remove"/>
-        /// <seealso cref="TryGetValue"/>
-        /// <seealso cref="Clear"/>
-        /// <seealso cref="PurgeExpired"/>
-        void RemoveRange(IEnumerable<TKey> keys);
-
-        /// <summary>
-        /// Add or replace an element with the provided <paramref name="key"/>, <paramref name="value"/> and <paramref name="size"/> to
-        /// <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </summary>
-        /// <param name="key">
-        /// The object used as the key of the element. Can't be <see langword="null"/> reference.
-        /// </param>
-        /// <param name="value">
-        /// The object used as the value of the element to add or replace. <see langword="null"/> is allowed.
-        /// </param>
-        /// <param name="size">
-        /// The element's size. Normally bytes, but can be any suitable unit of measure.
-        /// </param>
-        /// <returns>
-        /// <see langword="true"/> if element has been added successfully to the <see cref="ICnmCache{TKey,TValue}"/>;
-        /// otherwise <see langword="false"/>.
-        /// </returns>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <exception cref="ArgumentOutOfRangeException">
-        /// The element's <paramref name="size"/> is less than 0.
-        /// </exception>
-        /// <remarks>
-        /// <para>
-        /// If element's <paramref name="size"/> is larger than <see cref="MaxElementSize"/>, then element is
-        /// not added to the <see cref="ICnmCache{TKey,TValue}"/>, however - possible older element is
-        /// removed from the <see cref="ICnmCache{TKey,TValue}"/>.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting total size of elements,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// <para>
-        /// When adding an new element to <see cref="ICnmCache{TKey,TValue}"/> that is limiting element count,
-        /// <see cref="ICnmCache{TKey,TValue}"/>will remove less recently used elements until it can fit an new element.
-        /// </para>
-        /// </remarks>
-        /// <seealso cref="IsSizeLimited"/>
-        /// <seealso cref="IsCountLimited"/>
-        /// <seealso cref="Remove"/>
-        /// <seealso cref="RemoveRange"/>
-        /// <seealso cref="TryGetValue"/>
-        /// <seealso cref="Clear"/>
-        /// <seealso cref="PurgeExpired"/>
-        bool Set(TKey key, TValue value, long size);
-
-        /// <summary>
-        /// Gets the <paramref name="value"/> associated with the specified <paramref name="key"/>.
-        /// </summary>
-        /// <returns>
-        /// <see langword="true"/>if the <see cref="ICnmCache{TKey,TValue}"/> contains an element with
-        /// the specified key; otherwise, <see langword="false"/>.
-        /// </returns>
-        /// <param name="key">
-        /// The key whose <paramref name="value"/> to get.
-        /// </param>
-        /// <param name="value">
-        /// When this method returns, the value associated with the specified <paramref name="key"/>,
-        /// if the <paramref name="key"/> is found; otherwise, the
-        /// default value for the type of the <paramref name="value"/> parameter. This parameter is passed uninitialized.
-        /// </param>
-        /// <exception cref="ArgumentNullException">
-        /// <paramref name="key"/>is <see langword="null"/>.
-        /// </exception>
-        /// <seealso cref="Set"/>
-        /// <seealso cref="Remove"/>
-        /// <seealso cref="RemoveRange"/>
-        /// <seealso cref="Clear"/>
-        /// <seealso cref="PurgeExpired"/>
-        bool TryGetValue(TKey key, out TValue value);
-    }
-}

+ 0 - 419
OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs

@@ -1,419 +0,0 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the OpenSimulator Project nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Reflection;
-using log4net;
-using Mono.Addins;
-using Nini.Config;
-using OpenSim.Framework;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes;
-
-namespace OpenSim.Region.CoreModules.Asset
-{
-    /// <summary>
-    /// Cenome memory asset cache.
-    /// </summary>
-    /// <remarks>
-    /// <para>
-    /// Cache is enabled by setting "AssetCaching" configuration to value "CenomeMemoryAssetCache".
-    /// When cache is successfully enable log should have message
-    /// "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = XXX bytes, MaxCount = XXX, ExpirationTime = XXX)".
-    /// </para>
-    /// <para>
-    /// Cache's size is limited by two parameters:
-    /// maximal allowed size in bytes and maximal allowed asset count. When new asset
-    /// is added to cache that have achieved either size or count limitation, cache
-    /// will automatically remove less recently used assets from cache. Additionally
-    /// asset's lifetime is controlled by expiration time.
-    /// </para>
-    /// <para>
-    /// <list type="table">
-    /// <listheader>
-    /// <term>Configuration</term>
-    /// <description>Description</description>
-    /// </listheader>
-    /// <item>
-    /// <term>MaxSize</term>
-    /// <description>Maximal size of the cache in bytes. Default value: 128MB (134 217 728 bytes).</description>
-    /// </item>
-    /// <item>
-    /// <term>MaxCount</term>
-    /// <description>Maximal count of assets stored to cache. Default value: 4096 assets.</description>
-    /// </item>
-    /// <item>
-    /// <term>ExpirationTime</term>
-    /// <description>Asset's expiration time in minutes. Default value: 30 minutes.</description>
-    /// </item>
-    /// </list>
-    /// </para>
-    /// </remarks>
-    /// <example>
-    /// Enabling Cenome Asset Cache:
-    /// <code>
-    /// [Modules]
-    /// AssetCaching = "CenomeMemoryAssetCache"
-    /// </code>
-    /// Setting size and expiration time limitations:
-    /// <code>
-    /// [AssetCache]
-    /// ; 256 MB (default: 134217728)
-    /// MaxSize =  268435456
-    /// ; How many assets it is possible to store cache (default: 4096)
-    /// MaxCount = 16384
-    /// ; Expiration time - 1 hour (default: 30 minutes)
-    /// ExpirationTime = 60
-    /// </code>
-    /// </example>
-    [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")]
-    public class CenomeMemoryAssetCache : IAssetCache, ISharedRegionModule
-    {
-        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
-        /// <summary>
-        /// Cache's default maximal asset count.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Assuming that average asset size is about 32768 bytes.
-        /// </para>
-        /// </remarks>
-        public const int DefaultMaxCount = 4096;
-
-        /// <summary>
-        /// Default maximal size of the cache in bytes
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// 128MB = 128 * 1024^2 = 134 217 728 bytes.
-        /// </para>
-        /// </remarks>
-        public const long DefaultMaxSize = 134217728;
-
-        /// <summary>
-        /// Asset's default expiration time in the cache.
-        /// </summary>
-        public static readonly TimeSpan DefaultExpirationTime = TimeSpan.FromMinutes(30.0);
-
-        /// <summary>
-        /// Cache object.
-        /// </summary>
-        private ICnmCache<string, AssetBase> m_cache;
-
-        /// <summary>
-        /// Count of cache commands
-        /// </summary>
-        private int m_cachedCount;
-
-        /// <summary>
-        /// How many gets before dumping statistics
-        /// </summary>
-        /// <remarks>
-        /// If 0 or less, then disabled.
-        /// </remarks>
-        private int m_debugEpoch;
-
-        /// <summary>
-        /// Is Cenome asset cache enabled.
-        /// </summary>
-        private bool m_enabled;
-
-        /// <summary>
-        /// Count of get requests
-        /// </summary>
-        private int m_getCount;
-
-        /// <summary>
-        /// How many hits
-        /// </summary>
-        private int m_hitCount;
-
-        /// <summary>
-        /// Initialize asset cache module, with custom parameters.
-        /// </summary>
-        /// <param name="maximalSize">
-        /// Cache's maximal size in bytes.
-        /// </param>
-        /// <param name="maximalCount">
-        /// Cache's maximal count of assets.
-        /// </param>
-        /// <param name="expirationTime">
-        /// Asset's expiration time.
-        /// </param>
-        protected void Initialize(long maximalSize, int maximalCount, TimeSpan expirationTime)
-        {
-            if (maximalSize <= 0 || maximalCount <= 0)
-            {
-                //m_log.Debug("[ASSET CACHE]: Cenome asset cache is not enabled.");
-                m_enabled = false;
-                return;
-            }
-
-            if (expirationTime <= TimeSpan.Zero)
-            {
-                // Disable expiration time
-                expirationTime = TimeSpan.MaxValue;
-            }
-
-            // Create cache and add synchronization wrapper over it
-            m_cache =
-                CnmSynchronizedCache<string, AssetBase>.Synchronized(new CnmMemoryCache<string, AssetBase>(
-                    maximalSize, maximalCount, expirationTime));
-            m_enabled = true;
-            m_log.DebugFormat(
-                "[ASSET CACHE]: Cenome asset cache enabled (MaxSize = {0} bytes, MaxCount = {1}, ExpirationTime = {2})",
-                maximalSize,
-                maximalCount,
-                expirationTime);
-        }
-
-        #region IAssetCache Members
-
-        public bool Check(string id)
-        {
-            AssetBase asset;
-
-            // XXX:This is probably not an efficient implementation.
-            return m_cache.TryGetValue(id, out asset);
-        }
-
-        /// <summary>
-        /// Cache asset.
-        /// </summary>
-        /// <param name="asset">
-        /// The asset that is being cached.
-        /// </param>
-        public void Cache(AssetBase asset, bool replace = true)
-        {
-            if (asset != null)
-            {
-//                m_log.DebugFormat("[CENOME ASSET CACHE]: Caching asset {0}", asset.ID);
-
-                long size = asset.Data != null ? asset.Data.Length : 1;
-                m_cache.Set(asset.ID, asset, size);
-                m_cachedCount++;
-            }
-
-        }
-
-        public void CacheNegative(string id)
-        {
-            // We don't do negative caching
-        }
-
-        /// <summary>
-        /// Clear asset cache.
-        /// </summary>
-        public void Clear()
-        {
-            m_cache.Clear();
-        }
-
-        /// <summary>
-        /// Expire (remove) asset stored to cache.
-        /// </summary>
-        /// <param name="id">
-        /// The expired asset's id.
-        /// </param>
-        public void Expire(string id)
-        {
-            m_cache.Remove(id);
-        }
-
-        /// <summary>
-        /// Get asset stored
-        /// </summary>
-        /// <param name="id">
-        /// The asset's id.
-        /// </param>
-        /// <returns>
-        /// Asset if it is found from cache; otherwise <see langword="null"/>.
-        /// </returns>
-        /// <remarks>
-        /// <para>
-        /// Caller should always check that is return value <see langword="null"/>.
-        /// Cache doesn't guarantee in any situation that asset is stored to it.
-        /// </para>
-        /// </remarks>
-        public bool Get(string id, out AssetBase assetBase)
-        {
-            m_getCount++;
-            if (m_cache.TryGetValue(id, out assetBase))
-                m_hitCount++;
-
-            if (m_getCount == m_debugEpoch)
-            {
-                m_log.DebugFormat(
-                    "[ASSET CACHE]: Cached = {0}, Get = {1}, Hits = {2}%, Size = {3} bytes, Avg. A. Size = {4} bytes",
-                    m_cachedCount,
-                    m_getCount,
-                    ((double) m_hitCount / m_getCount) * 100.0,
-                    m_cache.Size,
-                    m_cache.Size / m_cache.Count);
-                m_getCount = 0;
-                m_hitCount = 0;
-                m_cachedCount = 0;
-            }
-
-//            if (null == assetBase)
-//                m_log.DebugFormat("[CENOME ASSET CACHE]: Asset {0} not in cache", id);
-
-            return true;
-        }
-
-        #endregion
-
-        #region ISharedRegionModule Members
-
-        /// <summary>
-        /// Gets region module's name.
-        /// </summary>
-        public string Name
-        {
-            get { return "CenomeMemoryAssetCache"; }
-        }
-
-        public Type ReplaceableInterface
-        {
-            get { return null; }
-        }
-
-        /// <summary>
-        /// New region is being added to server.
-        /// </summary>
-        /// <param name="scene">
-        /// Region's scene.
-        /// </param>
-        public void AddRegion(Scene scene)
-        {
-            if (m_enabled)
-                scene.RegisterModuleInterface<IAssetCache>(this);
-        }
-
-        /// <summary>
-        /// Close region module.
-        /// </summary>
-        public void Close()
-        {
-            if (m_enabled)
-            {
-                m_enabled = false;
-                m_cache.Clear();
-                m_cache = null;
-            }
-        }
-
-        /// <summary>
-        /// Initialize region module.
-        /// </summary>
-        /// <param name="source">
-        /// Configuration source.
-        /// </param>
-        public void Initialise(IConfigSource source)
-        {
-            m_cache = null;
-            m_enabled = false;
-
-            IConfig moduleConfig = source.Configs[ "Modules" ];
-            if (moduleConfig == null)
-                return;
-
-            string name = moduleConfig.GetString("AssetCaching");
-            //m_log.DebugFormat("[XXX] name = {0} (this module's name: {1}", name, Name);
-
-            if (name != Name)
-                return;
-
-            long maxSize = DefaultMaxSize;
-            int maxCount = DefaultMaxCount;
-            TimeSpan expirationTime = DefaultExpirationTime;
-
-            IConfig assetConfig = source.Configs["AssetCache"];
-            if (assetConfig != null)
-            {
-                // Get optional configurations
-                maxSize = assetConfig.GetLong("MaxSize", DefaultMaxSize);
-                maxCount = assetConfig.GetInt("MaxCount", DefaultMaxCount);
-                expirationTime =
-                    TimeSpan.FromMinutes(assetConfig.GetInt("ExpirationTime", (int)DefaultExpirationTime.TotalMinutes));
-
-                // Debugging purposes only
-                m_debugEpoch = assetConfig.GetInt("DebugEpoch", 0);
-            }
-
-            Initialize(maxSize, maxCount, expirationTime);
-        }
-
-        /// <summary>
-        /// Initialization post handling.
-        /// </summary>
-        /// <remarks>
-        /// <para>
-        /// Modules can use this to initialize connection with other modules.
-        /// </para>
-        /// </remarks>
-        public void PostInitialise()
-        {
-        }
-
-        /// <summary>
-        /// Region has been loaded.
-        /// </summary>
-        /// <param name="scene">
-        /// Region's scene.
-        /// </param>
-        /// <remarks>
-        /// <para>
-        /// This is needed for all module types. Modules will register
-        /// Interfaces with scene in AddScene, and will also need a means
-        /// to access interfaces registered by other modules. Without
-        /// this extra method, a module attempting to use another modules'
-        /// interface would be successful only depending on load order,
-        /// which can't be depended upon, or modules would need to resort
-        /// to ugly kludges to attempt to request interfaces when needed
-        /// and unnecessary caching logic repeated in all modules.
-        /// The extra function stub is just that much cleaner.
-        /// </para>
-        /// </remarks>
-        public void RegionLoaded(Scene scene)
-        {
-        }
-
-        /// <summary>
-        /// Region is being removed.
-        /// </summary>
-        /// <param name="scene">
-        /// Region scene that is being removed.
-        /// </param>
-        public void RemoveRegion(Scene scene)
-        {
-        }
-
-        #endregion
-    }
-}

+ 0 - 14
bin/config-include/CenomeCache.ini.example

@@ -1,14 +0,0 @@
-[AssetCache]
-    ;;
-    ;; Options for CenomeAssetCache
-    ;;
-
-    ; Max size of the cache in bytes
-    ; 134217728 = 128 MB, 26843556 = 256 MB, etc (default: 134217728)
-    MaxSize = 134217728
-
-    ; How many assets it is possible to store in the cache (default: 4096)
-    MaxCount = 4096
-
-    ; Expiration time in minutes (default: 30)
-    ExpirationTime = 30

+ 2 - 6
bin/config-include/GridCommon.ini.example

@@ -64,16 +64,12 @@
 
 
 [Modules]
-    ;; Choose one cache module and the corresponding config file, if it exists.
-    ;; Copy the config .example file into your own .ini file and adapt that.
-    ;; We recommend the use of the FlotsamAssetCache since this is most actively maintained.
+    ;; Asset cache module.
+    ;; Warning this is required for several region features
 
     AssetCaching = "FlotsamAssetCache"
     Include-FlotsamCache = "config-include/FlotsamCache.ini"
 
-    ;AssetCaching = "CenomeMemoryAssetCache"
-    ;Include-CenomeCache = "config-include/CenomeCache.ini"
-
     ;; Optionally, the port for the LLProxyLoginModule module can be changed
     ;Setup_LLProxyLoginModule = "9090/"
 

+ 2 - 6
bin/config-include/StandaloneCommon.ini.example

@@ -66,16 +66,12 @@
     ; HomeURIAlias = myoldname.something.org, 127.0.0.1,127.0.0.1:8043	
 
 [Modules]
-    ;; Choose one cache module and the corresponding config file, if it exists.
-    ;; Copy the config .example file into your own .ini file and alter that
-    ;; We recommend the use of the FlotsamAssetCache since this is most actively maintained.
+    ;; Asset cache module.
+    ;; Warning this is required for several region features
 
     AssetCaching = "FlotsamAssetCache"
     Include-FlotsamCache = "config-include/FlotsamCache.ini"
 
-    ;AssetCaching = "CenomeMemoryAssetCache"
-    ;Include-CenomeCache = "config-include/CenomeCache.ini"
-
     ;; Authorization is not on by default, as it depends on external php
     ;AuthorizationServices = "LocalAuthorizationServicesConnector"