1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
16 using System.ComponentModel;
17 using System.Diagnostics;
18 using System.Dynamic.Utils;
20 namespace System.Runtime.CompilerServices {
22 /// This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
23 /// Represents a cache of runtime binding rules.
25 /// <typeparam name="T">The delegate type.</typeparam>
26 [EditorBrowsable(EditorBrowsableState.Never), DebuggerStepThrough]
27 public class RuleCache<T> where T : class {
28 private T[] _rules = new T[0];
29 private readonly Object cacheLock = new Object();
31 private const int MaxRules = 128;
33 internal RuleCache() { }
35 internal T[] GetRules() {
39 // move the rule +2 up.
40 // this is called on every successful rule.
41 internal void MoveRule(T rule, int i) {
42 // limit search to MaxSearch elements.
43 // Rule should not get too far unless it has been already moved up.
44 // need a lock to make sure we are moving the right rule and not loosing any.
46 const int MaxSearch = 8;
47 int count = _rules.Length - i;
48 if (count > MaxSearch) {
53 int max = Math.Min(_rules.Length, i + count);
54 for (int index = i; index < max; index++) {
55 if (_rules[index] == rule) {
63 T oldRule = _rules[oldIndex];
64 _rules[oldIndex] = _rules[oldIndex - 1];
65 _rules[oldIndex - 1] = _rules[oldIndex - 2];
66 _rules[oldIndex - 2] = oldRule;
70 internal void AddRule(T newRule) {
71 // need a lock to make sure we are not loosing rules.
73 _rules = AddOrInsert(_rules, newRule);
77 internal void ReplaceRule(T oldRule, T newRule) {
78 // need a lock to make sure we are replacing the right rule
80 int i = Array.IndexOf(_rules, oldRule);
87 _rules = AddOrInsert(_rules, newRule);
92 // Adds to end or or inserts items at InsertPosition
93 private const int InsertPosition = MaxRules / 2;
95 private static T[] AddOrInsert(T[] rules, T item) {
96 if (rules.Length < InsertPosition) {
97 return rules.AddLast(item);
102 int newLength = rules.Length + 1;
103 if (newLength > MaxRules) {
104 newLength = MaxRules;
107 newRules = new T[newLength];
110 Array.Copy(rules, 0, newRules, 0, InsertPosition);
111 newRules[InsertPosition] = item;
112 Array.Copy(rules, InsertPosition, newRules, InsertPosition + 1, newLength - InsertPosition - 1);