PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Utils/CopyOnWriteList.cs

#
C# | 159 lines | 105 code | 27 blank | 27 comment | 10 complexity | 607ef084d2153d191f8506a8702d08af MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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.Collections.Generic;
  16. using System.Threading;
  17. using Microsoft.Contracts;
  18. namespace Microsoft.Scripting.Utils {
  19. /// <summary>
  20. /// List optimized for few writes and multiple reads. It provides thread-safe read and write access.
  21. /// Iteration is not thread-safe by default, but GetCopyForRead allows for iteration
  22. /// without taking a lock.
  23. /// </summary>
  24. public class CopyOnWriteList<T> : IList<T> {
  25. List<T> _list = new List<T>();
  26. List<T> GetNewListForWrite() {
  27. List<T> oldList = _list;
  28. List<T> newList = new List<T>(oldList.Count + 1);
  29. newList.AddRange(oldList);
  30. return newList;
  31. }
  32. /// <summary>
  33. /// Gets a copy of the contents of the list. The copy will not change even if the original
  34. /// CopyOnWriteList object is modified. This method should be used to iterate the list in
  35. /// a thread-safe way if no lock is taken. Iterating on the original list is not guaranteed
  36. /// to be thread-safe.
  37. /// </summary>
  38. /// <returns>The returned copy should not be modified by the caller.</returns>
  39. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] // TODO: fix
  40. public List<T> GetCopyForRead() {
  41. // Just return the underlying list
  42. return _list;
  43. }
  44. #region IList<T> Members
  45. public int IndexOf(T item) {
  46. return _list.IndexOf(item);
  47. }
  48. public void Insert(int index, T item) {
  49. List<T> oldList, replacedList;
  50. do {
  51. oldList = _list;
  52. List<T> newList = GetNewListForWrite();
  53. newList.Insert(index, item);
  54. replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
  55. } while (replacedList != oldList);
  56. }
  57. public void RemoveAt(int index) {
  58. List<T> oldList, replacedList;
  59. do {
  60. oldList = _list;
  61. List<T> newList = GetNewListForWrite();
  62. newList.RemoveAt(index);
  63. replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
  64. } while (replacedList != oldList);
  65. }
  66. public T this[int index] {
  67. get {
  68. return _list[index];
  69. }
  70. set {
  71. List<T> oldList, replacedList;
  72. do {
  73. oldList = _list;
  74. List<T> newList = GetNewListForWrite();
  75. newList[index] = value;
  76. replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
  77. } while (replacedList != oldList);
  78. }
  79. }
  80. #endregion
  81. #region ICollection<T> Members
  82. public void Add(T item) {
  83. List<T> oldList, replacedList;
  84. do {
  85. oldList = _list;
  86. List<T> newList = GetNewListForWrite();
  87. newList.Add(item);
  88. replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
  89. } while (replacedList != oldList);
  90. }
  91. public void Clear() {
  92. _list = new List<T>();
  93. }
  94. [Confined]
  95. public bool Contains(T item) {
  96. return _list.Contains(item);
  97. }
  98. public void CopyTo(T[] array, int arrayIndex) {
  99. _list.CopyTo(array, arrayIndex);
  100. }
  101. public int Count {
  102. get { return _list.Count; }
  103. }
  104. public bool IsReadOnly {
  105. get { return false; }
  106. }
  107. public bool Remove(T item) {
  108. List<T> oldList, replacedList;
  109. bool ret;
  110. do {
  111. oldList = _list;
  112. List<T> newList = GetNewListForWrite();
  113. ret = newList.Remove(item);
  114. replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
  115. } while (replacedList != oldList);
  116. return ret;
  117. }
  118. #endregion
  119. #region IEnumerable<T> Members
  120. [Pure]
  121. public IEnumerator<T> GetEnumerator() {
  122. return _list.GetEnumerator();
  123. }
  124. #endregion
  125. #region IEnumerable Members
  126. [Pure]
  127. System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
  128. return ((System.Collections.IEnumerable)_list).GetEnumerator();
  129. }
  130. #endregion
  131. }
  132. }