//****************************************************************************************************** // IndexedArray.cs - Gbtc // // Copyright © 2016, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 06/29/2016 - Steven E. Chisholm // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections; using System.Collections.Generic; using System.Threading; namespace GSF.Collections { /// /// A self growing array of items. This class is thread safe. /// /// public sealed class IndexedArray : IEnumerable { private T[] m_items; private object m_syncRoot; private T m_defaultValue; private bool m_defaultSet; /// /// Creates an . /// public IndexedArray() { m_items = new T[32]; m_syncRoot = new object(); m_defaultSet = false; m_defaultValue = default(T); } /// /// Creates an . /// public IndexedArray(T defaultValue) { m_defaultValue = defaultValue; m_items = new T[32]; m_syncRoot = new object(); m_defaultSet = true; for (int x = 0; x < 32; x++) { m_items[x] = defaultValue; } } /// /// Gets/Sets the items in this array. Returns the default(t) if the item does not exist, /// or default(t) is the item in the list. /// /// the index position to lookup public T this[int index] { get { if ((uint)index >= (uint)m_items.Length) return m_defaultValue; return m_items[index]; } set { if ((uint)index >= (uint)m_items.Length) { Grow(index); } m_items[index] = value; } } private void Grow(int index) { lock (m_syncRoot) { if (index < 0) throw new Exception("Index cannot be negative."); while (index >= m_items.Length) { T[] items = new T[m_items.Length * 2]; if (m_defaultSet) { for (int x = m_items.Length; x < items.Length; x++) { items[x] = m_defaultValue; } } m_items.CopyTo(items, 0); Thread.MemoryBarrier(); m_items = items; } } } /// /// Sets all items to their default value /// public void Clear() { lock (m_syncRoot) { if (m_defaultSet) { for (int x = m_items.Length; x < m_items.Length; x++) { m_items[x] = m_defaultValue; } } else { Array.Clear(m_items, 0, m_items.Length); } } } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)m_items).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return m_items.GetEnumerator(); } } }