aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/MapAndArray.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/MapAndArray.cs189
1 files changed, 189 insertions, 0 deletions
diff --git a/OpenSim/Framework/MapAndArray.cs b/OpenSim/Framework/MapAndArray.cs
new file mode 100644
index 0000000..c98d3cc
--- /dev/null
+++ b/OpenSim/Framework/MapAndArray.cs
@@ -0,0 +1,189 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// Stores two synchronized collections: a mutable dictionary and an
35 /// immutable array. Slower inserts/removes than a normal dictionary,
36 /// but provides safe iteration while maintaining fast hash lookups
37 /// </summary>
38 /// <typeparam name="TKey">Key type to use for hash lookups</typeparam>
39 /// <typeparam name="TValue">Value type to store</typeparam>
40 public sealed class MapAndArray<TKey, TValue>
41 {
42 private Dictionary<TKey, TValue> m_dict;
43 private TValue[] m_array;
44 private object m_syncRoot = new object();
45
46 /// <summary>Number of values currently stored in the collection</summary>
47 public int Count { get { return m_array.Length; } }
48 /// <summary>NOTE: This collection is thread safe. You do not need to
49 /// acquire a lock to add, remove, or enumerate entries. This
50 /// synchronization object should only be locked for larger
51 /// transactions</summary>
52 public object SyncRoot { get { return m_syncRoot; } }
53
54 /// <summary>
55 /// Constructor
56 /// </summary>
57 public MapAndArray()
58 {
59 m_dict = new Dictionary<TKey, TValue>();
60 m_array = new TValue[0];
61 }
62
63 /// <summary>
64 /// Constructor
65 /// </summary>
66 /// <param name="capacity">Initial capacity of the dictionary</param>
67 public MapAndArray(int capacity)
68 {
69 m_dict = new Dictionary<TKey, TValue>(capacity);
70 m_array = new TValue[0];
71 }
72
73 /// <summary>
74 /// Adds a key/value pair to the collection, or updates an existing key
75 /// with a new value
76 /// </summary>
77 /// <param name="key">Key to add or update</param>
78 /// <param name="value">Value to add</param>
79 /// <returns>True if a new key was added, false if an existing key was
80 /// updated</returns>
81 public bool AddOrReplace(TKey key, TValue value)
82 {
83 lock (m_syncRoot)
84 {
85 bool containedKey = m_dict.ContainsKey(key);
86
87 m_dict[key] = value;
88 CreateArray();
89
90 return !containedKey;
91 }
92 }
93
94 /// <summary>
95 /// Adds a key/value pair to the collection. This will throw an
96 /// exception if the key is already present in the collection
97 /// </summary>
98 /// <param name="key">Key to add or update</param>
99 /// <param name="value">Value to add</param>
100 /// <returns>Index of the inserted item</returns>
101 public int Add(TKey key, TValue value)
102 {
103 lock (m_syncRoot)
104 {
105 m_dict.Add(key, value);
106 CreateArray();
107 return m_array.Length;
108 }
109 }
110
111 /// <summary>
112 /// Removes a key/value pair from the collection
113 /// </summary>
114 /// <param name="key">Key to remove</param>
115 /// <returns>True if the key was found and removed, otherwise false</returns>
116 public bool Remove(TKey key)
117 {
118 lock (m_syncRoot)
119 {
120 bool removed = m_dict.Remove(key);
121 CreateArray();
122
123 return removed;
124 }
125 }
126
127 /// <summary>
128 /// Determines whether the collections contains a specified key
129 /// </summary>
130 /// <param name="key">Key to search for</param>
131 /// <returns>True if the key was found, otherwise false</returns>
132 public bool ContainsKey(TKey key)
133 {
134 lock (m_syncRoot)
135 return m_dict.ContainsKey(key);
136 }
137
138 /// <summary>
139 /// Gets the value associated with the specified key
140 /// </summary>
141 /// <param name="key">Key of the value to get</param>
142 /// <param name="value">Will contain the value associated with the
143 /// given key if the key is found. If the key is not found it will
144 /// contain the default value for the type of the value parameter</param>
145 /// <returns>True if the key was found and a value was retrieved,
146 /// otherwise false</returns>
147 public bool TryGetValue(TKey key, out TValue value)
148 {
149 lock (m_syncRoot)
150 return m_dict.TryGetValue(key, out value);
151 }
152
153 /// <summary>
154 /// Clears all key/value pairs from the collection
155 /// </summary>
156 public void Clear()
157 {
158 lock (m_syncRoot)
159 {
160 m_dict = new Dictionary<TKey, TValue>();
161 m_array = new TValue[0];
162 }
163 }
164
165 /// <summary>
166 /// Gets a reference to the immutable array of values stored in this
167 /// collection. This array is thread safe for iteration
168 /// </summary>
169 /// <returns>A thread safe reference ton an array of all of the stored
170 /// values</returns>
171 public TValue[] GetArray()
172 {
173 return m_array;
174 }
175
176 private void CreateArray()
177 {
178 // Rebuild the array from the dictionary. This method must be
179 // called from inside a lock
180 TValue[] array = new TValue[m_dict.Count];
181 int i = 0;
182
183 foreach (TValue value in m_dict.Values)
184 array[i++] = value;
185
186 m_array = array;
187 }
188 }
189}