Ejemplo n.º 1
0
        /// <summary>
        /// Returns the index of the entry to replace in a given set of the <see cref="Cache{TItem, UKey, VData}"/>; this could be an empty entry or an entry that should be replaced
        /// </summary>
        /// <param name="startIndex">The starting index of the set</param>
        /// <param name="endIndex">The ending index of the set</param>
        /// <returns>An index inclusively between <c>startIndex</c> and <c>endIndex</c> that should be replaced</returns>
        protected int GetReplacementIndex(int startIndex, int endIndex)
        {
            // readlock needed
            cacheLock.EnterReadLock();
            try
            {
                // first check if we have an empty block to use
                int ans = GetFirstEmptyIndex(startIndex, endIndex);
                // if so use that for the put
                if (ans > -1)
                {
                    return(ans);
                }

                // otherwise we'll need to use our IReplacementAlgorithm to figure out which block to use
                // Using ArraySegment wrapped in a ReadOnlyCollection we can referencially pass the set
                // we need for full inspection quickly without increasing memory footprint too much, since
                // we're not copying elements, but we don't risk the consumer trying to edit the cache (that's our job)
                ans = _replacementFinder.GetReplacementIndex(
                    new ReadOnlyCollection <TItem>(
                        (IList <TItem>) new ArraySegment <TItem>(_cacheArray, startIndex, endIndex - startIndex + 1)));

                // Make sure replacement strategy didn't do something crazy
                if (ans < 0 || ans > (endIndex - startIndex))
                {
                    throw new ArgumentException(string.Format("IReplacementAlgorithm ({0}) returned invalid index value.", _replacementFinder.GetType().FullName), "replacementAlgo");
                }

                // determine index in full cache
                return(startIndex + ans);
            }
            finally
            { cacheLock.ExitReadLock(); }
        }