diff options
Diffstat (limited to 'src/Common/src/System/Collections')
4 files changed, 164 insertions, 3 deletions
diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs index cc7edb0a4..bbb5959ca 100644 --- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs +++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs @@ -102,7 +102,7 @@ namespace System.Collections.Concurrent // State of a key must never go from found to not found, and only one value may exist per key. Debug.Assert(checkedFound); if (default(V) == null) // No good way to do the "only one value" check for value types. - Debug.Assert(Object.ReferenceEquals(checkedValue, value)); + Debug.Assert(object.ReferenceEquals(checkedValue, value)); } } #endif //DEBUG diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs index 8324b6c39..b2b70d8af 100644 --- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs +++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs @@ -112,7 +112,7 @@ namespace System.Collections.Concurrent // Since this DEBUG code is holding a strong reference to "value", state of a key must never go from found to not found, // and only one value may exist per key. Debug.Assert(checkedFound); - Debug.Assert(Object.ReferenceEquals(checkedValue, value)); + Debug.Assert(object.ReferenceEquals(checkedValue, value)); GC.KeepAlive(value); } } diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs index 8aa21984d..5dfcab17a 100644 --- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs +++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs @@ -125,7 +125,7 @@ namespace System.Collections.Concurrent // Since this DEBUG code is holding a strong reference to "value", state of a key must never go from found to not found, // and only one value may exist per key. Debug.Assert(checkedFound); - Debug.Assert(Object.ReferenceEquals(checkedValue, value)); + Debug.Assert(object.ReferenceEquals(checkedValue, value)); GC.KeepAlive(value); } } diff --git a/src/Common/src/System/Collections/Generic/LowLevelStack.cs b/src/Common/src/System/Collections/Generic/LowLevelStack.cs new file mode 100644 index 000000000..b193036a2 --- /dev/null +++ b/src/Common/src/System/Collections/Generic/LowLevelStack.cs @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** +** Private version of Stack<T> for internal System.Private.CoreLib use. This +** permits sharing more source between BCL and System.Private.CoreLib (as well as the +** fact that Stack<T> is just a useful class in general.) +** +** This does not strive to implement the full api surface area +** (but any portion it does implement should match the real Stack<T>'s +** behavior.) +** +===========================================================*/ + +namespace System.Collections.Generic +{ + // Implements a variable-size Stack that uses an array of objects to store the + // elements. A Stack has a capacity, which is the allocated length + // of the internal array. As elements are added to a Stack, the capacity + // of the Stack is automatically increased as required by reallocating the + // internal array. + // + /// <summary> + /// LowLevelStack with no interface implementation to minimize both code and data size + /// Data size is smaller because there will be minimal virtual function table. + /// Code size is smaller because only functions called will be in the binary. + /// </summary> + internal class LowLevelStack<T> + { + protected T[] _items; + protected int _size; + protected int _version; + + private static readonly T[] s_emptyArray = new T[0]; + + public LowLevelStack() + { + _items = s_emptyArray; + } + + public LowLevelStack(int capacity) + { + if (capacity < 0) + throw new ArgumentOutOfRangeException(nameof(capacity)); + + if (capacity == 0) + _items = s_emptyArray; + else + { + _size = capacity; + _items = new T[capacity]; + } + } + + public LowLevelStack(IEnumerable<T> collection) + { + if (collection == null) + throw new ArgumentNullException(nameof(collection)); + + ICollection<T> c = collection as ICollection<T>; + if (c != null) + { + int count = c.Count; + if (count == 0) + { + _items = s_emptyArray; + } + else + { + _items = new T[count]; + c.CopyTo(_items, 0); + _size = count; + } + } + else + { + _size = 0; + _items = s_emptyArray; + + using (IEnumerator<T> en = collection.GetEnumerator()) + { + while (en.MoveNext()) + { + Push(en.Current); + } + } + } + } + + public int Count + { + get + { + return _items.Length; + } + } + + public void Push(T item) + { + _size = _size + 1; + Array.Resize(ref _items, _size); + _items[_size - 1] = item; + _version++; + } + + public T Pop() + { + ThrowIfEmptyStack(); + + _size = _size - 1; + T item = _items[_size]; + Array.Resize(ref _items, _size); + _version++; + return item; + } + + public bool TryPop(out T result) + { + if (_size == 0) + { + result = default; + return false; + } + + _size = _size - 1; + result = _items[_size]; + Array.Resize(ref _items, _size); + _version++; + + return true; + } + + public T Peek() + { + ThrowIfEmptyStack(); + return _items[_size - 1]; + } + + public bool TryPeek(out T result) + { + if (_size == 0) + { + result = default; + return false; + } + + result = _items[_size - 1]; + _version++; + return true; + } + + private void ThrowIfEmptyStack() + { + if (_size == 0) + throw new InvalidOperationException(); + } + } +} |