PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Types/CustomInstanceDictionaryStorage.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 206 lines | 137 code | 31 blank | 38 comment | 33 complexity | 04a07b75ea7bf5e8a60aefc466e8a213 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. 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 Microsoft Public License, 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 Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using Microsoft.Scripting;
  19. using Microsoft.Scripting.Runtime;
  20. using System.Threading;
  21. namespace IronPython.Runtime.Types {
  22. /// <summary>
  23. /// Provides custom, versioned, dictionary access for instances. Used for both
  24. /// new-style and old-style instances.
  25. ///
  26. /// Each class can allocate a version for instance storage using the
  27. /// CustomInstanceDictionaryStorage.AllocateInstance method. The version allocated
  28. /// is dependent upon the names which are likely to appear in the instance
  29. /// dictionary. Currently these names are calculated by collecting the names
  30. /// that are assigned to during the __init__ method and combining these with
  31. /// all such names in the types MRO.
  32. ///
  33. /// When creating the dictionary for storing instance values the class can then create
  34. /// a PythonDictionary backed by a CustomInstanceDictionaryStorage with it's
  35. /// version. When doing a get/set optimized code can then be produced that
  36. /// verifies we have CustomInstanceDictionaryStorage and it has the
  37. /// correct version. If we have a matching dictionary then gets/sets can turn
  38. /// into simple array accesses rather than dictionary gets/sets. For programs
  39. /// which access a large number of instance variables this can dramatically
  40. /// speed up the program.
  41. ///
  42. /// TODO: Should we attempt to unify all versions which share the same keys?
  43. /// </summary>
  44. [Serializable]
  45. internal sealed class CustomInstanceDictionaryStorage : StringDictionaryStorage {
  46. private readonly int _keyVersion;
  47. private readonly string[] _extraKeys;
  48. private readonly object[] _values;
  49. [MultiRuntimeAware]
  50. private static int _namesVersion;
  51. internal static int AllocateVersion() {
  52. return Interlocked.Increment(ref _namesVersion);
  53. }
  54. public CustomInstanceDictionaryStorage(string[] extraKeys, int keyVersion) {
  55. _extraKeys = extraKeys;
  56. _keyVersion = keyVersion;
  57. _values = new object[extraKeys.Length];
  58. for (int i = 0; i < _values.Length; i++) {
  59. _values[i] = Uninitialized.Instance;
  60. }
  61. }
  62. public override void Add(object key, object value) {
  63. int ikey = FindKey(key);
  64. if (ikey != -1) {
  65. _values[ikey] = value;
  66. return;
  67. }
  68. base.Add(key, value);
  69. }
  70. public override void AddNoLock(object key, object value) {
  71. int ikey = FindKey(key);
  72. if (ikey != -1) {
  73. _values[ikey] = value;
  74. return;
  75. }
  76. base.AddNoLock(key, value);
  77. }
  78. public override bool Contains(object key) {
  79. int ikey = FindKey(key);
  80. if (ikey != -1) {
  81. return _values[ikey] != Uninitialized.Instance;
  82. }
  83. return base.Contains(key);
  84. }
  85. public override bool Remove(object key) {
  86. int ikey = FindKey(key);
  87. if (ikey != -1) {
  88. if (Interlocked.Exchange<object>(ref _values[ikey], Uninitialized.Instance) != Uninitialized.Instance) {
  89. return true;
  90. }
  91. return false;
  92. }
  93. return base.Remove(key);
  94. }
  95. public override bool TryGetValue(object key, out object value) {
  96. int ikey = FindKey(key);
  97. if (ikey != -1) {
  98. value = _values[ikey];
  99. if (value != Uninitialized.Instance) {
  100. return true;
  101. }
  102. value = null;
  103. return false;
  104. }
  105. return base.TryGetValue(key, out value);
  106. }
  107. public override int Count {
  108. get {
  109. int count = base.Count;
  110. foreach (object o in _values) {
  111. if (o != Uninitialized.Instance) {
  112. count++;
  113. }
  114. }
  115. return count;
  116. }
  117. }
  118. public override void Clear() {
  119. for (int i = 0; i < _values.Length; i++) {
  120. _values[i] = Uninitialized.Instance;
  121. }
  122. base.Clear();
  123. }
  124. public override List<KeyValuePair<object, object>> GetItems() {
  125. List<KeyValuePair<object, object>> res = base.GetItems();
  126. for (int i = 0; i < _extraKeys.Length; i++) {
  127. if (!String.IsNullOrEmpty(_extraKeys[i]) && _values[i] != Uninitialized.Instance) {
  128. res.Add(new KeyValuePair<object, object>(_extraKeys[i], _values[i]));
  129. }
  130. }
  131. return res;
  132. }
  133. public int KeyVersion {
  134. get {
  135. return _keyVersion;
  136. }
  137. }
  138. public int FindKey(object key) {
  139. string strKey = key as string;
  140. if (strKey != null) {
  141. return FindKey(strKey);
  142. }
  143. return -1;
  144. }
  145. public int FindKey(string key) {
  146. for (int i = 0; i < _extraKeys.Length; i++) {
  147. if (_extraKeys[i] == key) {
  148. return i;
  149. }
  150. }
  151. return -1;
  152. }
  153. public bool TryGetValue(int index, out object value) {
  154. value = _values[index];
  155. return value != Uninitialized.Instance;
  156. }
  157. public object GetValueHelper(int index, object oldInstance) {
  158. object ret = _values[index];
  159. if (ret != Uninitialized.Instance) return ret;
  160. //TODO this should go to a faster path since we know it's not in the dict
  161. return ((OldInstance)oldInstance).GetBoundMember(null, _extraKeys[index]);
  162. }
  163. public bool TryGetValueHelper(int index, object oldInstance, out object res) {
  164. res = _values[index];
  165. if (res != Uninitialized.Instance) {
  166. return true;
  167. }
  168. //TODO this should go to a faster path since we know it's not in the dict
  169. return ((OldInstance)oldInstance).TryGetBoundCustomMember(null, _extraKeys[index], out res);
  170. }
  171. public void SetExtraValue(int index, object value) {
  172. _values[index] = value;
  173. }
  174. }
  175. }