PageRenderTime 25ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 1ms 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
  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
 16using System.Collections.Generic;
 17using System.Threading;
 18using Microsoft.Contracts;
 19
 20namespace Microsoft.Scripting.Utils {
 21    /// <summary>
 22    /// List optimized for few writes and multiple reads. It provides thread-safe read and write access. 
 23    /// Iteration is not thread-safe by default, but GetCopyForRead allows for iteration 
 24    /// without taking a lock.
 25    /// </summary>
 26    public class CopyOnWriteList<T> : IList<T> {
 27        List<T> _list = new List<T>();
 28
 29        List<T> GetNewListForWrite() {
 30            List<T> oldList = _list;
 31            List<T> newList = new List<T>(oldList.Count + 1);
 32            newList.AddRange(oldList);
 33            return newList;
 34        }
 35
 36        /// <summary>
 37        /// Gets a copy of the contents of the list. The copy will not change even if the original
 38        /// CopyOnWriteList object is modified. This method should be used to iterate the list in
 39        /// a thread-safe way if no lock is taken. Iterating on the original list is not guaranteed 
 40        /// to be thread-safe.
 41        /// </summary>
 42        /// <returns>The returned copy should not be modified by the caller.</returns>
 43        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] // TODO: fix
 44        public List<T> GetCopyForRead() {
 45            // Just return the underlying list
 46            return _list;
 47        }
 48
 49        #region IList<T> Members
 50
 51        public int IndexOf(T item) {
 52            return _list.IndexOf(item);
 53        }
 54
 55        public void Insert(int index, T item) {
 56            List<T> oldList, replacedList;
 57            do {
 58                oldList = _list;
 59                List<T> newList = GetNewListForWrite();
 60                newList.Insert(index, item);
 61                replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
 62            } while (replacedList != oldList);
 63        }
 64
 65        public void RemoveAt(int index) {
 66            List<T> oldList, replacedList;
 67            do {
 68                oldList = _list;
 69                List<T> newList = GetNewListForWrite();
 70                newList.RemoveAt(index);
 71                replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
 72            } while (replacedList != oldList);
 73        }
 74
 75        public T this[int index] {
 76            get {
 77                return _list[index];
 78            }
 79
 80            set {
 81                List<T> oldList, replacedList;
 82                do {
 83                    oldList = _list;
 84                    List<T> newList = GetNewListForWrite();
 85                    newList[index] = value;
 86                    replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
 87                } while (replacedList != oldList);
 88            }
 89        }
 90
 91        #endregion
 92
 93        #region ICollection<T> Members
 94
 95        public void Add(T item) {
 96            List<T> oldList, replacedList;
 97            do {
 98                oldList = _list;
 99                List<T> newList = GetNewListForWrite();
100                newList.Add(item);
101                replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
102            } while (replacedList != oldList);
103        }
104
105        public void Clear() {
106            _list = new List<T>();
107        }
108
109        [Confined]
110        public bool Contains(T item) {
111            return _list.Contains(item);
112        }
113
114        public void CopyTo(T[] array, int arrayIndex) {
115            _list.CopyTo(array, arrayIndex);
116        }
117
118        public int Count {
119            get { return _list.Count; }
120        }
121
122        public bool IsReadOnly {
123            get { return false; }
124        }
125
126        public bool Remove(T item) {
127            List<T> oldList, replacedList;
128            bool ret;
129            do {
130                oldList = _list;
131                List<T> newList = GetNewListForWrite();
132                ret = newList.Remove(item);
133                replacedList = Interlocked.CompareExchange(ref _list, newList, oldList);
134            } while (replacedList != oldList);
135
136            return ret;
137        }
138
139        #endregion
140
141        #region IEnumerable<T> Members
142
143        [Pure]
144        public IEnumerator<T> GetEnumerator() {
145            return _list.GetEnumerator();
146        }
147
148        #endregion
149
150        #region IEnumerable Members
151
152        [Pure]
153        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
154            return ((System.Collections.IEnumerable)_list).GetEnumerator();
155        }
156
157        #endregion
158    }
159}