| File: System\Runtime\CompilerServices\RuleCache.cs | Web Access |
| Project: src\runtime\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.Diagnostics; using System.Dynamic.Utils; namespace System.Runtime.CompilerServices { /// <summary> /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code. /// Represents a cache of runtime binding rules. /// </summary> /// <typeparam name="T">The delegate type.</typeparam> [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough] public class RuleCache<T> where T : class { private T[] _rules = Array.Empty<T>(); private readonly object _cacheLock = new object(); private const int MaxRules = 128; internal RuleCache() { } internal T[] GetRules() { return _rules; } // move the rule +2 up. // this is called on every successful rule. internal void MoveRule(T rule, int i) { // limit search to MaxSearch elements. // Rule should not get too far unless it has been already moved up. // need a lock to make sure we are moving the right rule and not losing any. lock (_cacheLock) { const int MaxSearch = 8; int count = _rules.Length - i; if (count > MaxSearch) { count = MaxSearch; } int oldIndex = -1; int max = Math.Min(_rules.Length, i + count); for (int index = i; index < max; index++) { if (_rules[index] == rule) { oldIndex = index; break; } } if (oldIndex < 2) { return; } T oldRule = _rules[oldIndex]; _rules[oldIndex] = _rules[oldIndex - 1]; _rules[oldIndex - 1] = _rules[oldIndex - 2]; _rules[oldIndex - 2] = oldRule; } } internal void AddRule(T newRule) { // need a lock to make sure we are not losing rules. lock (_cacheLock) { _rules = AddOrInsert(_rules, newRule); } } // Adds to end or inserts items at InsertPosition private const int InsertPosition = MaxRules / 2; private static T[] AddOrInsert(T[] rules, T item) { if (rules.Length < InsertPosition) { return rules.AddLast(item); } T[] newRules; int newLength = rules.Length + 1; if (newLength > MaxRules) { newLength = MaxRules; newRules = rules; } else { newRules = new T[newLength]; Array.Copy(rules, newRules, InsertPosition); } newRules[InsertPosition] = item; Array.Copy(rules, InsertPosition, newRules, InsertPosition + 1, newLength - InsertPosition - 1); return newRules; } } }