From 860b2a502f797e5822c6705d4639f370f3ac5861 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 16 Sep 2010 17:30:46 -0700 Subject: Changed SceneObjectGroup to store parts with the fast and thread-safe MapAndArray collection --- OpenSim/Framework/MapAndArray.cs | 188 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 OpenSim/Framework/MapAndArray.cs (limited to 'OpenSim/Framework/MapAndArray.cs') diff --git a/OpenSim/Framework/MapAndArray.cs b/OpenSim/Framework/MapAndArray.cs new file mode 100644 index 0000000..bbe6a9e --- /dev/null +++ b/OpenSim/Framework/MapAndArray.cs @@ -0,0 +1,188 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; + +namespace OpenSim.Framework +{ + /// + /// Stores two synchronized collections: a mutable dictionary and an + /// immutable array. Slower inserts/removes than a normal dictionary, + /// but provides safe iteration while maintaining fast hash lookups + /// + /// Key type to use for hash lookups + /// Value type to store + public sealed class MapAndArray + { + private Dictionary m_dict; + private TValue[] m_array; + private object m_syncRoot = new object(); + + /// Number of values currently stored in the collection + public int Count { get { return m_array.Length; } } + /// NOTE: This collection is thread safe. You do not need to + /// acquire a lock to add, remove, or enumerate entries. This + /// synchronization object should only be locked for larger + /// transactions + public object SyncRoot { get { return m_syncRoot; } } + + /// + /// Constructor + /// + public MapAndArray() + { + m_dict = new Dictionary(); + m_array = new TValue[0]; + } + + /// + /// Constructor + /// + /// Initial capacity of the dictionary + public MapAndArray(int capacity) + { + m_dict = new Dictionary(capacity); + m_array = new TValue[0]; + } + + /// + /// Adds a key/value pair to the collection, or updates an existing key + /// with a new value + /// + /// Key to add or update + /// Value to add + /// True if a new key was added, false if an existing key was + /// updated + public bool AddOrReplace(TKey key, TValue value) + { + lock (m_syncRoot) + { + bool containedKey = m_dict.ContainsKey(key); + + m_dict[key] = value; + CreateArray(); + + return !containedKey; + } + } + + /// + /// Adds a key/value pair to the collection. This will throw an + /// exception if the key is already present in the collection + /// + /// Key to add or update + /// Value to add + /// Index of the inserted item + public int Add(TKey key, TValue value) + { + lock (m_syncRoot) + { + m_dict.Add(key, value); + CreateArray(); + return m_array.Length; + } + } + + /// + /// Removes a key/value pair from the collection + /// + /// Key to remove + /// True if the key was found and removed, otherwise false + public bool Remove(TKey key) + { + lock (m_syncRoot) + { + bool removed = m_dict.Remove(key); + CreateArray(); + + return removed; + } + } + + /// + /// Determines whether the collections contains a specified key + /// + /// Key to search for + /// True if the key was found, otherwise false + public bool ContainsKey(TKey key) + { + return m_dict.ContainsKey(key); + } + + /// + /// Gets the value associated with the specified key + /// + /// Key of the value to get + /// Will contain the value associated with the + /// given key if the key is found. If the key is not found it will + /// contain the default value for the type of the value parameter + /// True if the key was found and a value was retrieved, + /// otherwise false + public bool TryGetValue(TKey key, out TValue value) + { + lock (m_syncRoot) + return m_dict.TryGetValue(key, out value); + } + + /// + /// Clears all key/value pairs from the collection + /// + public void Clear() + { + lock (m_syncRoot) + { + m_dict = new Dictionary(); + m_array = new TValue[0]; + } + } + + /// + /// Gets a reference to the immutable array of values stored in this + /// collection. This array is thread safe for iteration + /// + /// A thread safe reference ton an array of all of the stored + /// values + public TValue[] GetArray() + { + return m_array; + } + + private void CreateArray() + { + // Rebuild the array from the dictionary. This method must be + // called from inside a lock + TValue[] array = new TValue[m_dict.Count]; + int i = 0; + + foreach (TValue value in m_dict.Values) + array[i++] = value; + + m_array = array; + } + } +} -- cgit v1.1