/Languages/IronPython/IronPython/Runtime/SysModuleDictionaryStorage.cs

http://github.com/IronLanguages/main · C# · 249 lines · 203 code · 24 blank · 22 comment · 38 complexity · c7b5f7ee2539c2522e8a23766da9dfd1 MD5 · raw file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  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.
  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.Text;
  18. using IronPython.Modules;
  19. using Microsoft.Scripting.Runtime;
  20. using IronPython.Runtime.Operations;
  21. namespace IronPython.Runtime {
  22. /// <summary>
  23. /// Optimized storage for setting exc_type, exc_value, and exc_traceback.
  24. ///
  25. /// This optimization can go away in Python 3.0 when these attributes are no longer used.
  26. /// </summary>
  27. class SysModuleDictionaryStorage : ModuleDictionaryStorage {
  28. private ExceptionState _exceptionState = null;
  29. private object _excType, _excValue, _excTraceback;
  30. private ExceptionStateFlags _setValues = ExceptionStateFlags.Traceback | ExceptionStateFlags.Type | ExceptionStateFlags.Value, _removedValues;
  31. public SysModuleDictionaryStorage()
  32. : base(typeof(SysModule)) {
  33. }
  34. public override void Add(ref DictionaryStorage storage, object key, object value) {
  35. lock (this) {
  36. AddNoLock(ref storage, key, value);
  37. }
  38. }
  39. public override void AddNoLock(ref DictionaryStorage storage, object key, object value) {
  40. // add always needs to check...
  41. string strKey = key as string;
  42. if (strKey != null) {
  43. switch (strKey) {
  44. case "exc_type":
  45. _setValues |= ExceptionStateFlags.Type;
  46. _removedValues &= ~ExceptionStateFlags.Type;
  47. _excType = value;
  48. break;
  49. case "exc_value":
  50. _setValues |= ExceptionStateFlags.Value;
  51. _removedValues &= ~ExceptionStateFlags.Value;
  52. _excValue = value;
  53. break;
  54. case "exc_traceback":
  55. _setValues |= ExceptionStateFlags.Traceback;
  56. _removedValues &= ~ExceptionStateFlags.Traceback;
  57. _excTraceback = value;
  58. break;
  59. }
  60. }
  61. base.AddNoLock(ref storage, key, value);
  62. }
  63. public override bool Remove(ref DictionaryStorage storage, object key) {
  64. // check the strKey only if we have some exception info set
  65. ExceptionState exState = _exceptionState;
  66. if (exState != null || _setValues != 0) {
  67. string strKey = key as string;
  68. if (strKey != null) {
  69. switch (strKey) {
  70. case "exc_type":
  71. lock (this) {
  72. _excType = null;
  73. _setValues &= ~ExceptionStateFlags.Type;
  74. _removedValues |= ExceptionStateFlags.Type;
  75. }
  76. break;
  77. case "exc_value":
  78. lock (this) {
  79. _excValue = null;
  80. _setValues &= ~ExceptionStateFlags.Value;
  81. _removedValues |= ExceptionStateFlags.Value;
  82. }
  83. break;
  84. case "exc_traceback":
  85. lock (this) {
  86. _excTraceback = null;
  87. _setValues &= ~ExceptionStateFlags.Traceback;
  88. _removedValues |= ExceptionStateFlags.Traceback;
  89. }
  90. break;
  91. }
  92. }
  93. }
  94. return base.Remove(ref storage, key);
  95. }
  96. public override bool TryGetValue(object key, out object value) {
  97. ExceptionState exState = _exceptionState;
  98. // check the strKey only if we have some exception info set
  99. if (exState != null || _setValues != 0) {
  100. string strKey = key as string;
  101. if (strKey != null && TryGetExcValue(exState, strKey, out value)) {
  102. return true;
  103. }
  104. }
  105. return base.TryGetValue(key, out value);
  106. }
  107. private bool TryGetExcValue(ExceptionState exState, string strKey, out object value) {
  108. switch (strKey) {
  109. case "exc_type":
  110. lock (this) {
  111. if ((_removedValues & ExceptionStateFlags.Type) == 0) {
  112. if ((_setValues & ExceptionStateFlags.Type) != 0) {
  113. value = _excType;
  114. } else {
  115. value = exState.Type;
  116. }
  117. return true;
  118. }
  119. }
  120. break;
  121. case "exc_value":
  122. lock (this) {
  123. if ((_removedValues & ExceptionStateFlags.Value) == 0) {
  124. if ((_setValues & ExceptionStateFlags.Value) != 0) {
  125. value = _excValue;
  126. } else {
  127. value = exState.Value;
  128. }
  129. return true;
  130. }
  131. }
  132. break;
  133. case "exc_traceback":
  134. lock (this) {
  135. if ((_removedValues & ExceptionStateFlags.Traceback) == 0) {
  136. if ((_setValues & ExceptionStateFlags.Traceback) != 0) {
  137. value = _excTraceback;
  138. } else {
  139. _excTraceback = CreateTraceBack(exState);
  140. _setValues |= ExceptionStateFlags.Traceback;
  141. value = _excTraceback;
  142. }
  143. return true;
  144. }
  145. }
  146. break;
  147. }
  148. value = null;
  149. return false;
  150. }
  151. public override List<KeyValuePair<object, object>> GetItems() {
  152. var res = base.GetItems();
  153. object value;
  154. if (TryGetValue("exc_traceback", out value)) {
  155. res.Add(new KeyValuePair<object, object>("exc_traceback", value));
  156. }
  157. if (TryGetValue("exc_type", out value)) {
  158. res.Add(new KeyValuePair<object, object>("exc_type", value));
  159. }
  160. if (TryGetValue("exc_value", out value)) {
  161. res.Add(new KeyValuePair<object, object>("exc_value", value));
  162. }
  163. return res;
  164. }
  165. private static object CreateTraceBack(ExceptionState list) {
  166. return PythonOps.CreateTraceBack(list.ClrException, list.Traceback, list.FrameCount);
  167. }
  168. public override void Clear(ref DictionaryStorage storage) {
  169. lock (this) {
  170. _exceptionState = null;
  171. _setValues = 0;
  172. _removedValues = 0;
  173. _excTraceback = _excType = _excValue = null;
  174. base.Clear(ref storage);
  175. }
  176. }
  177. [Flags]
  178. enum ExceptionStateFlags {
  179. Type = 0x01,
  180. Value = 0x02,
  181. Traceback = 0x04
  182. }
  183. class ExceptionState {
  184. public readonly object Type;
  185. public readonly object Value;
  186. public readonly List<DynamicStackFrame> Traceback;
  187. public readonly int FrameCount;
  188. public readonly Exception ClrException;
  189. public ExceptionState(Exception clrException, object type, object value, List<DynamicStackFrame> traceback) {
  190. Type = type;
  191. Value = value;
  192. Traceback = traceback;
  193. ClrException = clrException;
  194. if (traceback != null) {
  195. FrameCount = traceback.Count;
  196. }
  197. }
  198. }
  199. public void UpdateExceptionInfo(Exception clrException, object type, object value, List<DynamicStackFrame> traceback) {
  200. lock (this) {
  201. _exceptionState = new ExceptionState(clrException, type, value, traceback);
  202. _setValues = _removedValues = 0;
  203. }
  204. }
  205. public void UpdateExceptionInfo(object type, object value, object traceback) {
  206. lock (this) {
  207. _exceptionState = new ExceptionState(null, type, value, null);
  208. _excTraceback = traceback;
  209. _setValues = ExceptionStateFlags.Traceback;
  210. _removedValues = 0;
  211. }
  212. }
  213. public void ExceptionHandled() {
  214. lock (this) {
  215. _setValues = ExceptionStateFlags.Traceback | ExceptionStateFlags.Type | ExceptionStateFlags.Value;
  216. _removedValues = 0;
  217. _exceptionState = null;
  218. _excTraceback = _excType = _excValue = null;
  219. }
  220. }
  221. public override void Reload() {
  222. base.Reload();
  223. }
  224. }
  225. }