aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-08 17:34:51 -0700
committerJohn Hurliman2009-10-08 17:34:51 -0700
commit3a04d706c9ebd13214e62fb944b4a8da6860bb91 (patch)
tree2e6b2f83993e283acba5af07e91c0695c23ac333 /OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
parentPutting the lock back in TryGetValue. (diff)
downloadopensim-SC-3a04d706c9ebd13214e62fb944b4a8da6860bb91.zip
opensim-SC-3a04d706c9ebd13214e62fb944b4a8da6860bb91.tar.gz
opensim-SC-3a04d706c9ebd13214e62fb944b4a8da6860bb91.tar.bz2
opensim-SC-3a04d706c9ebd13214e62fb944b4a8da6860bb91.tar.xz
Fear the lockless LLUDP implementation!
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs252
1 files changed, 60 insertions, 192 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
index dbb9861..06fa3e2 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenMetaverse; 32using OpenMetaverse;
33using BclExtras.Collections;
33 34
34using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; 35using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
35 36
@@ -37,246 +38,113 @@ namespace OpenSim.Region.ClientStack.LindenUDP
37{ 38{
38 public sealed class UDPClientCollection 39 public sealed class UDPClientCollection
39 { 40 {
40 Dictionary<UUID, LLUDPClient> Dictionary1; 41 #region IComparers
41 Dictionary<IPEndPoint, LLUDPClient> Dictionary2;
42 LLUDPClient[] Array;
43 ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl();
44 object m_sync = new object();
45 42
46 public UDPClientCollection() 43 private sealed class UUIDComparer : IComparer<UUID>
47 {
48 Dictionary1 = new Dictionary<UUID, LLUDPClient>();
49 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>();
50 Array = new LLUDPClient[0];
51 }
52
53 public UDPClientCollection(int capacity)
54 { 44 {
55 Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity); 45 public int Compare(UUID x, UUID y)
56 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity); 46 {
57 Array = new LLUDPClient[0]; 47 return x.Guid.CompareTo(y.Guid);
48 }
58 } 49 }
59 50
60 public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) 51 private sealed class IPEndPointComparer : IComparer<IPEndPoint>
61 { 52 {
62 //rwLock.EnterWriteLock(); 53 public int Compare(IPEndPoint x, IPEndPoint y)
63
64 //try
65 //{
66 // if (Dictionary1.ContainsKey(key1))
67 // {
68 // if (!Dictionary2.ContainsKey(key2))
69 // throw new ArgumentException("key1 exists in the dictionary but not key2");
70 // }
71 // else if (Dictionary2.ContainsKey(key2))
72 // {
73 // if (!Dictionary1.ContainsKey(key1))
74 // throw new ArgumentException("key2 exists in the dictionary but not key1");
75 // }
76
77 // Dictionary1[key1] = value;
78 // Dictionary2[key2] = value;
79
80 // LLUDPClient[] oldArray = Array;
81 // int oldLength = oldArray.Length;
82
83 // LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
84 // for (int i = 0; i < oldLength; i++)
85 // newArray[i] = oldArray[i];
86 // newArray[oldLength] = value;
87
88 // Array = newArray;
89 //}
90 //finally { rwLock.ExitWriteLock(); }
91
92 lock (m_sync)
93 { 54 {
94 if (Dictionary1.ContainsKey(key1)) 55 int result = x.Address.Address.CompareTo(y.Address.Address);
95 { 56 if (result == 0) result = x.Port.CompareTo(y.Port);
96 if (!Dictionary2.ContainsKey(key2)) 57 return result;
97 throw new ArgumentException("key1 exists in the dictionary but not key2"); 58 }
98 } 59 }
99 else if (Dictionary2.ContainsKey(key2))
100 {
101 if (!Dictionary1.ContainsKey(key1))
102 throw new ArgumentException("key2 exists in the dictionary but not key1");
103 }
104
105 Dictionary1[key1] = value;
106 Dictionary2[key2] = value;
107
108 LLUDPClient[] oldArray = Array;
109 int oldLength = oldArray.Length;
110 60
111 LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; 61 #endregion IComparers
112 for (int i = 0; i < oldLength; i++)
113 newArray[i] = oldArray[i];
114 newArray[oldLength] = value;
115 62
116 Array = newArray; 63 private ImmutableMap<UUID, LLUDPClient> m_dict1;
117 } 64 private ImmutableMap<IPEndPoint, LLUDPClient> m_dict2;
65 private LLUDPClient[] m_array;
118 66
67 public UDPClientCollection()
68 {
69 m_dict1 = new ImmutableMap<UUID, LLUDPClient>(new UUIDComparer());
70 m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
71 m_array = new LLUDPClient[0];
119 } 72 }
120 73
121 public bool Remove(UUID key1, IPEndPoint key2) 74 public void Add(UUID key1, IPEndPoint key2, LLUDPClient value)
122 { 75 {
123 //rwLock.EnterWriteLock(); 76 m_dict1 = m_dict1.Add(key1, value);
124 77 m_dict2 = m_dict2.Add(key2, value);
125 //try 78
126 //{ 79 // Copy the array by hand
127 // LLUDPClient value; 80 LLUDPClient[] oldArray = m_array;
128 // if (Dictionary1.TryGetValue(key1, out value)) 81 int oldLength = oldArray.Length;
129 // { 82 LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
130 // Dictionary1.Remove(key1); 83
131 // Dictionary2.Remove(key2); 84 for (int i = 0; i < oldLength; i++)
85 newArray[i] = oldArray[i];
86 newArray[oldLength] = value;
87
88 m_array = newArray;
89 }
132 90
133 // LLUDPClient[] oldArray = Array; 91 public void Remove(UUID key1, IPEndPoint key2)
134 // int oldLength = oldArray.Length; 92 {
93 m_dict1 = m_dict1.Delete(key1);
94 m_dict2 = m_dict2.Delete(key2);
135 95
136 // LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; 96 LLUDPClient[] oldArray = m_array;
137 // int j = 0; 97 int oldLength = oldArray.Length;
138 // for (int i = 0; i < oldLength; i++)
139 // {
140 // if (oldArray[i] != value)
141 // newArray[j++] = oldArray[i];
142 // }
143 98
144 // Array = newArray; 99 // Copy the array by hand
145 // return true;
146 // }
147 //}
148 //finally { rwLock.ExitWriteLock(); }
149 100
150 //return false; 101 LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
102 int j = 0;
151 103
152 lock (m_sync) 104 for (int i = 0; i < oldLength; i++)
153 { 105 {
154 LLUDPClient value; 106 if (oldArray[i].AgentID != key1)
155 if (Dictionary1.TryGetValue(key1, out value)) 107 newArray[j++] = oldArray[i];
156 {
157 Dictionary1.Remove(key1);
158 Dictionary2.Remove(key2);
159
160 LLUDPClient[] oldArray = Array;
161 int oldLength = oldArray.Length;
162
163 LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
164 int j = 0;
165 for (int i = 0; i < oldLength; i++)
166 {
167 if (oldArray[i] != value)
168 newArray[j++] = oldArray[i];
169 }
170
171 Array = newArray;
172 return true;
173 }
174 } 108 }
175 109
176 return false; 110 m_array = newArray;
177
178 } 111 }
179 112
180 public void Clear() 113 public void Clear()
181 { 114 {
182 //rwLock.EnterWriteLock(); 115 m_dict1 = new ImmutableMap<UUID, LLUDPClient>(new UUIDComparer());
183 116 m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
184 //try 117 m_array = new LLUDPClient[0];
185 //{
186 // Dictionary1.Clear();
187 // Dictionary2.Clear();
188 // Array = new LLUDPClient[0];
189 //}
190 //finally { rwLock.ExitWriteLock(); }
191
192 lock (m_sync)
193 {
194 Dictionary1.Clear();
195 Dictionary2.Clear();
196 Array = new LLUDPClient[0];
197 }
198
199 } 118 }
200 119
201 public int Count 120 public int Count
202 { 121 {
203 get { return Array.Length; } 122 get { return m_array.Length; }
204 } 123 }
205 124
206 public bool ContainsKey(UUID key) 125 public bool ContainsKey(UUID key)
207 { 126 {
208 return Dictionary1.ContainsKey(key); 127 return m_dict1.ContainsKey(key);
209 } 128 }
210 129
211 public bool ContainsKey(IPEndPoint key) 130 public bool ContainsKey(IPEndPoint key)
212 { 131 {
213 return Dictionary2.ContainsKey(key); 132 return m_dict2.ContainsKey(key);
214 } 133 }
215 134
216 public bool TryGetValue(UUID key, out LLUDPClient value) 135 public bool TryGetValue(UUID key, out LLUDPClient value)
217 { 136 {
218 ////bool success; 137 return m_dict1.TryGetValue(key, out value);
219 ////bool doLock = !rwLock.IsUpgradeableReadLockHeld;
220 ////if (doLock) rwLock.EnterReadLock();
221
222 ////try { success = Dictionary1.TryGetValue(key, out value); }
223 ////finally { if (doLock) rwLock.ExitReadLock(); }
224
225 ////return success;
226
227 lock (m_sync)
228 return Dictionary1.TryGetValue(key, out value);
229
230 //try
231 //{
232 // return Dictionary1.TryGetValue(key, out value);
233 //}
234 //catch { }
235 //value = null;
236 //return false;
237 } 138 }
238 139
239 public bool TryGetValue(IPEndPoint key, out LLUDPClient value) 140 public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
240 { 141 {
241 ////bool success; 142 return m_dict2.TryGetValue(key, out value);
242 ////bool doLock = !rwLock.IsUpgradeableReadLockHeld;
243 ////if (doLock) rwLock.EnterReadLock();
244
245 ////try { success = Dictionary2.TryGetValue(key, out value); }
246 ////finally { if (doLock) rwLock.ExitReadLock(); }
247
248 ////return success;
249
250 lock (m_sync)
251 return Dictionary2.TryGetValue(key, out value);
252
253 //try
254 //{
255 // return Dictionary2.TryGetValue(key, out value);
256 //}
257 //catch { }
258 //value = null;
259 //return false;
260
261 } 143 }
262 144
263 public void ForEach(Action<LLUDPClient> action) 145 public void ForEach(Action<LLUDPClient> action)
264 { 146 {
265 //bool doLock = !rwLock.IsUpgradeableReadLockHeld; 147 Parallel.ForEach<LLUDPClient>(m_array, action);
266 //if (doLock) rwLock.EnterUpgradeableReadLock();
267
268 //try { Parallel.ForEach<LLUDPClient>(Array, action); }
269 //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); }
270
271 LLUDPClient[] localArray = null;
272 lock (m_sync)
273 {
274 localArray = new LLUDPClient[Array.Length];
275 Array.CopyTo(localArray, 0);
276 }
277
278 Parallel.ForEach<LLUDPClient>(localArray, action);
279
280 } 148 }
281 } 149 }
282} 150}