DynConcurrentList.cs

Dynamic Concurrent Generic List

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class DynConcurrentList<T> : MonitorActionFunc, IEnumerable<T>
{
    private          T[]        _array;
    private volatile MiniSet<T> _mSet;
    public volatile  int        Count;
    public DynConcurrentList() : this(101)
    {
    }
    public DynConcurrentList(IEnumerable<T> collection)
    {
        var enumerable = collection as T[] ?? collection.ToArray();
        Count  = enumerable.Length;
        _array = new T[Count];
        Array.Copy(enumerable, 0, _array, 0, Count);
    }
    public DynConcurrentList(int cap)
    {
        _array = new T[cap];
        Count  = 0;
    }
    public int Capacity
    {
        get
        {
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                return _array.Length;
            });
        }
        set
        {
            var tmpThis = this;
            tmpThis.Lock(tmpThis, () =>
            {
                Array.Resize(ref _array, value);
            });
        }
    }
    public T this[int index]
    {
        get
        {
            var array   = _array;
            var idx     = index;
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                if (idx > array.Length)
                    throw new Exception("Error: Index out of range.");
                return array[idx];
            });
        }
        set
        {
            var tmpThis = this;
            var idx     = index;
            tmpThis.Lock(tmpThis, () =>
            {
                if (idx >= _array.Length)
                    Array.Resize(ref _array, _array.Length + _array.Length / 4 * 3);
                _array[idx] = value;
            });
        }
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public void Add(T item)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if (Count >= _array.Length)
                Array.Resize(ref _array, _array.Length + _array.Length / 4 * 3);
            _array[Count] = item;
            Interlocked.Increment(ref Count);
        });
    }
    public void AddRange(IEnumerable<T> col)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            var enumerable = col as T[] ?? col.ToArray();
            for (var i = 0; i < enumerable.Length; ++i)
            {
                if (Count >= _array.Length)
                    Array.Resize(ref _array, _array.Length + _array.Length / 4 * 3);
                _array[Count] = enumerable[i];
                Interlocked.Increment(ref Count);
            }
        });
    }
    public void Clear()
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            Array.Clear(_array, 0, _array.Length);
            Count = 0;
        });
    }
    public void Clean()
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            var newtArray = new T[Count];
            Array.Copy(_array, 0, newtArray, 0, Count);
            _array = newtArray;
        });
    }
    public bool Contains(T item, IEqualityComparer<T> comparer = null)
    {
        if (comparer == null)
            comparer = EqualityComparer<T>.Default;
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            if (_mSet != null && _mSet.Count != Count)
            {
                _mSet = new MiniSet<T>(_array, comparer);
            }
            else
            {
                _mSet = new MiniSet<T>(Count, comparer);
                Clean();
                _mSet.AddRange(_array);
            }
            return _mSet.Contains(item);
        });
    }
    public void CopyTo(int index, T[] array, int arrayIndex, int count)
    {
        if (Capacity - index < count)
            throw new Exception("Collection too small.");
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            Array.Copy(_array, index, array, arrayIndex, count);
        });
    }
    public void ForEach(Action<T> action)
    {
        if (action == null)
            throw new Exception("Action cannot be null.");
        for (var index = 0; index < Count; ++index)
            action(_array[index]);
    }
    public void ParallelForEach(Action<T> action)
    {
        _array.AsParallel().ForAll(i =>
        {
            if (action == null)
                throw new Exception("Action cannot be null.");
            action(i);
        });
    }
    public int IndexOf(T item, int index)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            if (index > Count)
                throw new Exception("Index out of range.");
            return Array.IndexOf(_array, item, index, Count - index);
        });
    }
    public void RemoveAt(int index)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if ((uint) index >= (uint) Count)
                throw new Exception("Index out of range.");
            Interlocked.Decrement(ref Count);
            if (index < Count)
                Array.Copy(_array, index + 1, _array, index, Count - index);
            _array[Count] = default;
        });
    }
    public void Reverse()
    {
        Reverse(0, Count);
    }
    public void Reverse(int index, int count)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if (index < 0)
                throw new Exception("Index out of range.");
            if (count < 0)
                throw new Exception("Count out of range.");
            if (Count - index < count)
                throw new Exception("Invalid offset.");
            Clean();
            Array.Reverse(_array, index, count);
        });
    }
    public void Sort()
    {
        Sort(0, Count, null);
    }
    public void Sort(IComparer<T> comparer)
    {
        Sort(0, Count, comparer);
    }
    public void Sort(int index, int count, IComparer<T> comparer)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if (index < 0)
                throw new Exception("Index out of range.");
            if (count < 0)
                throw new Exception("Count out of range.");
            if (Count - index < count)
                throw new Exception("Invalid offset.");
            Array.Sort(_array, index, count, comparer);
        });
    }
    public IEnumerator<T> GetEnumerator()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            return GetEnum();
        });
    }
    public T[] ToArray()
    {
        Array.Resize(ref _array, Count);
        return _array;
    }
    private IEnumerator<T> GetEnum()
    {
        var array = _array;
        var count = Count;
        for (var i = 0; i < count; i++)
            yield return array[i];
    }
}

DynamicFSList.cs

Fast Search Concurrent Non-Concurrent List

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
[DebuggerDisplay("Count = {" + nameof(Count) + "}")]
public class DynamicFSList<T> : MonitorActionFunc, IEnumerable<T>
{
    private static IEqualityComparer<T> Comparer;
    private         VerticalList[]       _verticalLists;
    public          int                  Count;

    /// <summary>
    /// The initial size should be at least 1/8 of the expected total number of objects.
    /// For faster searching make initial size equal to the expected total number of objects.
    /// </summary>
    /// <param name="size"></param>
    public DynamicFSList(int size) : this(size, EqualityComparer<T>.Default)
    {
    }
    public DynamicFSList(int size, IEqualityComparer<T> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<T>.Default;
        Comparer       = comparer;
        _verticalLists = new VerticalList[size];
        Count          = 0;
    }
    public (int mDepth, int index) MaximumListLength => GetMaximumListLength();
    public int                     TrueItemCount     => GetItemCount();
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<T> GetEnumerator()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            return GetEnum();
        });
    }
    public void Clear()
    {
        _verticalLists.Clear();
    }
    public void Add(T item)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
            var pos      = hashCode % _verticalLists.Length;
            if (_verticalLists[pos] == null)
                _verticalLists[pos] = new VerticalList();
            _verticalLists[pos].Add(item);
            Count++;
            if (Count > _verticalLists.Length << 3)
                EnsureSize();
        });
    }
    public int AddWithLocation(T item)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
            var pos      = hashCode % _verticalLists.Length;
            if (_verticalLists[pos] == null)
                _verticalLists[pos] = new VerticalList();
            _verticalLists[pos].Add(item);
            Count++;
            if (Count > _verticalLists.Length << 3)
                EnsureSize();
            return FindEntry(item, hashCode);
        });
    }
    public T[] ToArray()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var newArray = new T[Count];
            var ptr      = 0;
            for (var i = 0; i < _verticalLists.Length; i++)
                if (_verticalLists[i] != null)
                    for (var j = 0; j < _verticalLists[i].Count; ++j)
                    {
                        newArray[ptr] = _verticalLists[i].Values[j];
                        ptr++;
                    }
            return newArray;
        });
    }
    private (int mDepth, int index) GetMaximumListLength()
    {
        var max = 0;
        var j   = 0;
        for (var i = 0; i < _verticalLists.Length; i++)
            if (_verticalLists[i] != null)
            {
                var count = _verticalLists[i].Count;
                if (count > max)
                {
                    max = count;
                    j   = i;
                }
            }
        return (max, j);
    }
    private int GetItemCount()
    {
        var count = 0;
        for (var i = 0; i < _verticalLists.Length; i++)
            if (_verticalLists[i] != null)
            {
                var c = _verticalLists[i].Count;
                count += c;
            }
        return count;
    }
    public int FindEntry(T item)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
            return FindEntry(item, hashCode);
        });
    }
    private int FindEntry(T item, int hashCode)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            if (Count == 0)
                return -1;
            var pos = hashCode % _verticalLists.Length;
            if (_verticalLists[pos] == null)
                _verticalLists[pos] = new VerticalList();
            foreach (var i in _verticalLists[pos].Values)
                if (Comparer.Equals(i, item))
                    return pos;
            return -1;
        });
    }
    private void EnsureSize()
    {
        var cArray  = ToArray();
        var newSize = Count >> (1 + Count);
        _verticalLists = new VerticalList[newSize];
        foreach (var i in cArray)
        {
            var hashCode = Comparer.GetHashCode(i) & int.MaxValue;
            var pos      = hashCode % _verticalLists.Length;
            if (_verticalLists[pos] == null)
                _verticalLists[pos] = new VerticalList();
            _verticalLists[pos].Add(i);
        }
    }
    public bool Contains(T item)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var hashCode = Comparer.GetHashCode(item) & int.MaxValue;
            return FindEntry(item, hashCode) != -1;
        });
    }
    private IEnumerator<T> GetEnum()
    {
        for (var i = 0; i < _verticalLists.Length; i++)
            if (_verticalLists[i] != null)
                for (var j = 0; j < _verticalLists[i].Count; ++j)
                    yield return _verticalLists[i].Values[j];
    }
    private class VerticalList
    {
        public int Count;
        public T[] Values;
        public VerticalList()
        {
            Values = new T[3];
            Count  = 0;
        }
        public void Add(T item)
        {
            if (Contains(item))
                return;
            if (Count >= Values.Length)
                Array.Resize(ref Values, Values.Length + 3);
            Values[Count] = item;
            Count++;
        }
        private bool Contains(T item)
        {
            foreach (var i in Values)
                if (Comparer.Equals(i, item))
                    return true;
            return false;
        }
    }
}

DynamicLimitedList.cs

Concurrent Non-Concurrent Limited List

using System;
using System.Collections;
using System.Collections.Generic;
[Serializable]
public class DynamicLimitedList<T> : MonitorActionFunc, IEnumerable<T>
{
    private volatile T[] _array;
    private volatile int _count;
    private volatile int _maxSize;
    public DynamicLimitedList(int maxsize)
    {
        _array   = new T[maxsize];
        _maxSize = maxsize;
    }
    public int MaxSize
    {
        get
        {
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                return _maxSize;
            });
        }
    }
    public int Count
    {
        get
        {
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                return _count;
            });
        }
    }
    public T this[int index]
    {
        get
        {
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                if (index > _array.Length - 1)
                    throw new Exception($"Index {index} is out of range {_array.Length - 1}");
                return _array[index];
            });
        }
        set
        {
            var tmpThis = this;
            tmpThis.Lock(tmpThis, () =>
            {
                if (index > _array.Length - 1)
                    throw new Exception($"Index {index} is out of range {_array.Length - 1}");
                if (index < _maxSize)
                {
                    _array[index] = value;
                    _count++;
                    if (_count > _maxSize)
                        _count = _maxSize;
                }
            });
        }
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public IEnumerator<T> GetEnumerator()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            return GetEnum();
        });
    }
    private IEnumerator<T> GetEnum()
    {
        var array = _array;
        var count = Count;
        for (var i = 0; i < count; i++)
            yield return array[i];
    }
    public void Add(T value)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if (_count == _maxSize)
            {
                LeftShift();
                _array[_maxSize - 1] = value;
            }
            else
            {
                _array[_count] = value;
                _count++;
            }
        });
    }
    private void LeftShift()
    {
        var TArray = new T[_maxSize];
        Array.Copy(_array, 1, TArray, 0, _maxSize - 1);
        _array = TArray;
    }
    public void Clear()
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            _array = new T[_maxSize];
            _count = 0;
        });
    }
    public bool Contains(T item)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var size             = _maxSize;
            var equalityComparer = EqualityComparer<T>.Default;
            while (size-- > 0)
                if (_array[size] != null && equalityComparer.Equals(_array[size], item))
                    return true;
            return false;
        });
    }
    public T[] ToArray()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var objArray = new T[_maxSize];
            Array.Copy(_array, 0, objArray, 0, _maxSize);
            return objArray;
        });
    }
    public List<T> ToList()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            return new List<T>(_array);
        });
    }
    public HashSet<T> ToHashSet()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            return new HashSet<T>(_array);
        });
    }
    public void CopyTo(T[] array)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            Array.Copy(_array, 0, array, 0, _maxSize);
        });
    }
}