DynamicStack.cs

A Concurrent or Non-Concurrent LIFO Collection of Objects

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
[DebuggerDisplay("Count = {Count}")]
[Serializable]
public class DynamicStack<T> : MonitorActionFunc, IEnumerable<T>
{
    private volatile T[] _array;
    private volatile int _count;
    public DynamicStack() : this(101)
    {
    }
    public DynamicStack(int capacity)
    {
        _array = new T[capacity];
        _count = 0;
    }
    public DynamicStack(ICollection col)
    {
        if (col != null)
        {
            _array = new T[col.Count];
            _count = 0;
            var en = col.GetEnumerator();
            while (en.MoveNext())
                Push((T) en.Current);
        }
    }
    public DynamicStack(IEnumerable<T> col)
    {
        if (col != null)
        {
            var enumerable = col as T[] ?? col.ToArray();
            _array = new T[enumerable.Length];
            foreach (var i in enumerable)
                Push(i);
        }
    }
    public int Count
    {
        get
        {
            var tmpThis = this;
            return tmpThis.Lock(tmpThis, () =>
            {
                return _count;
            });
        }
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return new Enumerator(this);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return new Enumerator(this);
    }
    public void Clear()
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            _array.Clear();
            _count = 0;
        });
    }
    public bool Contains(T item)
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var size             = _count;
            var equalityComparer = EqualityComparer<T>.Default;
            while (size-- > 0)
                if (_array[size] != null && equalityComparer.Equals(_array[size], item))
                    return true;
            return false;
        });
    }
    public T Peek()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () => _array[_count - 1]);
    }
    public T Pop()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            _count--;
            var TVal = _array[_count];
            _array[Count] = default;
            return TVal;
        });
    }
    public void Push(T item)
    {
        var tmpThis = this;
        tmpThis.Lock(tmpThis, () =>
        {
            if (_count + 1 > _array.Length)
                EnsureSize();
            _array[_count++] = item;
        });
    }
    private void EnsureSize()
    {
        var array = _array;
        Array.Resize(ref array, _array.Length << 1);
        _array = array;
    }
    public T[] ToArray()
    {
        var tmpThis = this;
        return tmpThis.Lock(tmpThis, () =>
        {
            var ta = new T[_count];
            for (var i = 0L; i < _count; ++i)
                ta[i] = _array[_count - i - 1];
            return ta;
        });
    }
    [Serializable]
    public class Enumerator : IEnumerator<T>
    {
        private readonly DynamicStack<T> _stack;
        private          int             _index;
        internal Enumerator(DynamicStack<T> stack)
        {
            _stack  = stack;
            _index  = int.MaxValue;
            Current = default;
        }
        public T Current
        {
            get;
            private set;
        }
        object IEnumerator.Current => Current;
        public void Dispose()
        {
            _index = int.MaxValue - 1;
        }
        public bool MoveNext()
        {
            var tmpThis = _stack;
            return tmpThis.Lock(tmpThis, () =>
            {
                if (_index == int.MaxValue)
                {
                    _index = _stack.Count - 1;
                    if (_index < int.MaxValue - 1)
                        Current = _stack._array[_index];
                    return _index < int.MaxValue - 1;
                }
                if (_index == int.MaxValue - 1)
                    return false;
                _index--;
                Current = !(_index < int.MaxValue - 1) ? default : _stack._array[_index];
                return _index < int.MaxValue - 1;
            });
        }
        void IEnumerator.Reset()
        {
            _index  = int.MaxValue;
            Current = default;
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *