aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-08 17:34:51 -0700
committerJohn Hurliman2009-10-08 17:34:51 -0700
commit3a04d706c9ebd13214e62fb944b4a8da6860bb91 (patch)
tree2e6b2f83993e283acba5af07e91c0695c23ac333
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!
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs252
-rw-r--r--ThirdPartyLicenses/BclExtras.txt60
-rw-r--r--ThirdPartyLicenses/CSJ2K.txt28
-rw-r--r--bin/BclExtras.dllbin0 -> 178688 bytes
-rw-r--r--prebuild.xml1
5 files changed, 149 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}
diff --git a/ThirdPartyLicenses/BclExtras.txt b/ThirdPartyLicenses/BclExtras.txt
new file mode 100644
index 0000000..a8a0292
--- /dev/null
+++ b/ThirdPartyLicenses/BclExtras.txt
@@ -0,0 +1,60 @@
1MICROSOFT PUBLIC LICENSE (Ms-PL)
2
3This license governs use of the accompanying software. If you use the software,
4you accept this license. If you do not accept the license, do not use the
5software.
6
71. Definitions
8
9The terms "reproduce," "reproduction," "derivative works," and "distribution"
10have the same meaning here as under U.S. copyright law.
11
12A "contribution" is the original software, or any additions or changes to the
13software.
14
15A "contributor" is any person that distributes its contribution under this
16license.
17
18"Licensed patents" are a contributor's patent claims that read directly on its
19contribution.
20
212. Grant of Rights
22
23(A) Copyright Grant- Subject to the terms of this license, including the license
24conditions and limitations in section 3, each contributor grants you a
25non-exclusive, worldwide, royalty-free copyright license to reproduce its
26contribution, prepare derivative works of its contribution, and distribute its
27contribution or any derivative works that you create.
28
29(B) Patent Grant- Subject to the terms of this license, including the license
30conditions and limitations in section 3, each contributor grants you a
31non-exclusive, worldwide, royalty-free license under its licensed patents to
32make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
33its contribution in the software or derivative works of the contribution in the
34software.
35
363. Conditions and Limitations
37
38(A) No Trademark License- This license does not grant you rights to use any
39contributors' name, logo, or trademarks.
40
41(B) If you bring a patent claim against any contributor over patents that you
42claim are infringed by the software, your patent license from such contributor
43to the software ends automatically.
44
45(C) If you distribute any portion of the software, you must retain all
46copyright, patent, trademark, and attribution notices that are present in the
47software.
48
49(D) If you distribute any portion of the software in source code form, you may
50do so only under this license by including a complete copy of this license with
51your distribution. If you distribute any portion of the software in compiled or
52object code form, you may only do so under a license that complies with this
53license.
54
55(E) The software is licensed "as-is." You bear the risk of using it. The
56contributors give no express warranties, guarantees or conditions. You may have
57additional consumer rights under your local laws which this license cannot
58change. To the extent permitted under your local laws, the contributors exclude
59the implied warranties of merchantability, fitness for a particular purpose and
60non-infringement.
diff --git a/ThirdPartyLicenses/CSJ2K.txt b/ThirdPartyLicenses/CSJ2K.txt
new file mode 100644
index 0000000..3032548
--- /dev/null
+++ b/ThirdPartyLicenses/CSJ2K.txt
@@ -0,0 +1,28 @@
1Copyright (c) 1999/2000 JJ2000 Partners.
2
3This software module was originally developed by Raphaël Grosbois and
4Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
5Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
6Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
7Centre France S.A) in the course of development of the JPEG2000
8standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
9software module is an implementation of a part of the JPEG 2000
10Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
11Systems AB and Canon Research Centre France S.A (collectively JJ2000
12Partners) agree not to assert against ISO/IEC and users of the JPEG
132000 Standard (Users) any of their rights under the copyright, not
14including other intellectual property rights, for this software module
15with respect to the usage by ISO/IEC and Users of this software module
16or modifications thereof for use in hardware or software products
17claiming conformance to the JPEG 2000 Standard. Those intending to use
18this software module in hardware or software products are advised that
19their use may infringe existing patents. The original developers of
20this software module, JJ2000 Partners and ISO/IEC assume no liability
21for use of this software module or modifications thereof. No license
22or right to this software module is granted for non JPEG 2000 Standard
23conforming products. JJ2000 Partners have full right to use this
24software module for his/her own purpose, assign or donate this
25software module to any third party and to inhibit third parties from
26using this software module for non JPEG 2000 Standard conforming
27products. This copyright notice must be included in all copies or
28derivative works of this software module.
diff --git a/bin/BclExtras.dll b/bin/BclExtras.dll
new file mode 100644
index 0000000..505cf01
--- /dev/null
+++ b/bin/BclExtras.dll
Binary files differ
diff --git a/prebuild.xml b/prebuild.xml
index bba54f3..028e5e7 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1767,6 +1767,7 @@
1767 <Reference name="OpenSim.Region.Communications.Local"/> 1767 <Reference name="OpenSim.Region.Communications.Local"/>
1768 <Reference name="OpenSim.Region.Physics.Manager"/> 1768 <Reference name="OpenSim.Region.Physics.Manager"/>
1769 <Reference name="OpenSim.Services.Interfaces"/> 1769 <Reference name="OpenSim.Services.Interfaces"/>
1770 <Reference name="BclExtras.dll"/>
1770 <Reference name="XMLRPC.dll"/> 1771 <Reference name="XMLRPC.dll"/>
1771 <Reference name="Nini.dll" /> 1772 <Reference name="Nini.dll" />
1772 <Reference name="log4net.dll"/> 1773 <Reference name="log4net.dll"/>