/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System.Collections; using System.Collections.Generic; using System.Threading; namespace wasSharp.Collections.Specialized { public static class ConcurrentListExtensions { public static ConcurrentList ToConcurrentList(this IEnumerable enumerable) { return new ConcurrentList(enumerable); } } public class ConcurrentList : IList { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); private readonly List _list; public ConcurrentList(IEnumerable v) { _lock.EnterWriteLock(); try { _list = new List(); foreach (var i in v) { _list.Add(i); } } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public ConcurrentList() { _lock.EnterWriteLock(); try { _list = new List(); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public bool IsReadOnly { get { _lock.EnterReadLock(); try { return ((IList)_list).IsReadOnly; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } int ICollection.Count { get { _lock.EnterReadLock(); try { return _list.Count; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public T this[int index] { get { _lock.EnterReadLock(); try { return _list[index]; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { _list[index] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public int IndexOf(T item) { _lock.EnterReadLock(); try { return _list.IndexOf(item); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } public void Insert(int index, T item) { _lock.EnterWriteLock(); try { _list.Insert(index, item); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public void RemoveAt(int index) { _lock.EnterWriteLock(); try { _list.RemoveAt(index); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public void Add(T item) { _lock.EnterWriteLock(); try { _list.Add(item); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public void Clear() { _lock.EnterWriteLock(); try { _list.Clear(); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public bool Contains(T item) { _lock.EnterReadLock(); try { return _list.Contains(item); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } public void CopyTo(T[] array, int arrayIndex) { _lock.EnterReadLock(); try { _list.CopyTo(array, arrayIndex); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } public bool Remove(T item) { _lock.EnterWriteLock(); try { return _list.Remove(item); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public IEnumerator GetEnumerator() { _lock.EnterReadLock(); try { using (var enumerator = _list.GetEnumerator()) { while (enumerator.MoveNext()) yield return enumerator.Current; } } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } IEnumerator IEnumerable.GetEnumerator() { _lock.EnterReadLock(); try { using (var enumerator = _list.GetEnumerator()) { while (enumerator.MoveNext()) yield return enumerator.Current; } } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } }