Advertisement
Guest User

Untitled

a guest
Nov 19th, 2017
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.44 KB | None | 0 0
  1. // Inspired by: http://www.nesterovsky-bros.com/weblog/2014/01/08/WeakTable.aspx
  2. public static class ObjectCache<T> where T : class
  3. {
  4. #region Inner classes
  5.  
  6. public enum ElementState : byte
  7. {
  8. Uninitialized = 0,
  9. Initialized = 1,
  10. Finalized = 2
  11. }
  12.  
  13. private class Element
  14. {
  15. public readonly T Value;
  16. public ElementState State;
  17.  
  18. public Element(T value)
  19. {
  20. State = ElementState.Uninitialized;
  21. Value = value;
  22. }
  23.  
  24. ~Element()
  25. {
  26. if (State == ElementState.Initialized)
  27. {
  28. State = ElementState.Finalized;
  29. WeakReference<Element> state;
  30. Values.TryRemove(this, out state);
  31. }
  32. }
  33.  
  34. public override int GetHashCode()
  35. {
  36. return Value.GetHashCode();
  37. }
  38. }
  39.  
  40. private class WeakEqualityComparer : IEqualityComparer<object>
  41. {
  42. private readonly IEqualityComparer<T> _innerComparer;
  43.  
  44. public WeakEqualityComparer(IEqualityComparer<T> innerComparer)
  45. {
  46. _innerComparer = innerComparer;
  47. }
  48.  
  49. public new bool Equals(object x, object y)
  50. {
  51. if (x == y) return true;
  52.  
  53. var xRef = x as WeakReference<Element>;
  54. var xElem = xRef == null ? x as Element : GetTarget(xRef);
  55.  
  56. var yRef = y as WeakReference<Element>;
  57. var yElem = yRef == null ? y as Element : GetTarget(yRef);
  58.  
  59. if (xElem == yElem) return true;
  60. if (xElem == null || yElem == null) return false;
  61.  
  62. // If xState is finalized, then we are within the Finalizer and we want to
  63. // search by reference to specifically remove this item.
  64. if (xElem.State == ElementState.Finalized) return false;
  65.  
  66. // If we are looking for an element but this one is currently being finalized,
  67. // we dont want to return it because it is going to disappear from the cache soon.
  68. if (xElem.State == ElementState.Uninitialized && yElem.State == ElementState.Finalized) return false;
  69.  
  70. return _innerComparer.Equals(xElem.Value, yElem.Value);
  71. }
  72.  
  73. public int GetHashCode(object obj)
  74. {
  75. return obj is WeakReference<Element>
  76. ? (GetTarget((WeakReference<Element>) obj)?.GetHashCode() ?? obj.GetHashCode())
  77. : obj.GetHashCode();
  78. }
  79. }
  80. #endregion Inner classes
  81.  
  82. private static readonly ConcurrentDictionary<object, WeakReference<Element>> Values = new ConcurrentDictionary<object, WeakReference<Element>>(new WeakEqualityComparer(EqualityComparer<T>.Default));
  83.  
  84. public static int Count => Values.Count;
  85.  
  86. public static T Intern(T item)
  87. {
  88. if (item == null)
  89. return null;
  90.  
  91. Element initialElement = new Element(item);
  92. WeakReference<Element> weakInitialState = new WeakReference<Element>(initialElement, true);
  93. Element newElement;
  94. do
  95. {
  96. newElement = GetTarget(Values.GetOrAdd(weakInitialState, x =>
  97. {
  98. initialElement.State = ElementState.Initialized;
  99. return weakInitialState;
  100. }));
  101. } while (newElement == null);
  102.  
  103. return newElement.Value;
  104. }
  105.  
  106. public static TRef GetTarget<TRef>(WeakReference<TRef> value) where TRef : class
  107. {
  108. TRef target;
  109. value.TryGetTarget(out target);
  110. return target;
  111. }
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement