From 3a04d706c9ebd13214e62fb944b4a8da6860bb91 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Oct 2009 17:34:51 -0700 Subject: Fear the lockless LLUDP implementation! --- .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 252 +++++---------------- 1 file changed, 60 insertions(+), 192 deletions(-) (limited to 'OpenSim/Region/ClientStack') 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; using System.Net; using OpenSim.Framework; using OpenMetaverse; +using BclExtras.Collections; using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; @@ -37,246 +38,113 @@ namespace OpenSim.Region.ClientStack.LindenUDP { public sealed class UDPClientCollection { - Dictionary Dictionary1; - Dictionary Dictionary2; - LLUDPClient[] Array; - ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl(); - object m_sync = new object(); + #region IComparers - public UDPClientCollection() - { - Dictionary1 = new Dictionary(); - Dictionary2 = new Dictionary(); - Array = new LLUDPClient[0]; - } - - public UDPClientCollection(int capacity) + private sealed class UUIDComparer : IComparer { - Dictionary1 = new Dictionary(capacity); - Dictionary2 = new Dictionary(capacity); - Array = new LLUDPClient[0]; + public int Compare(UUID x, UUID y) + { + return x.Guid.CompareTo(y.Guid); + } } - public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) + private sealed class IPEndPointComparer : IComparer { - //rwLock.EnterWriteLock(); - - //try - //{ - // if (Dictionary1.ContainsKey(key1)) - // { - // if (!Dictionary2.ContainsKey(key2)) - // throw new ArgumentException("key1 exists in the dictionary but not key2"); - // } - // else if (Dictionary2.ContainsKey(key2)) - // { - // if (!Dictionary1.ContainsKey(key1)) - // throw new ArgumentException("key2 exists in the dictionary but not key1"); - // } - - // Dictionary1[key1] = value; - // Dictionary2[key2] = value; - - // LLUDPClient[] oldArray = Array; - // int oldLength = oldArray.Length; - - // LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; - // for (int i = 0; i < oldLength; i++) - // newArray[i] = oldArray[i]; - // newArray[oldLength] = value; - - // Array = newArray; - //} - //finally { rwLock.ExitWriteLock(); } - - lock (m_sync) + public int Compare(IPEndPoint x, IPEndPoint y) { - if (Dictionary1.ContainsKey(key1)) - { - if (!Dictionary2.ContainsKey(key2)) - throw new ArgumentException("key1 exists in the dictionary but not key2"); - } - else if (Dictionary2.ContainsKey(key2)) - { - if (!Dictionary1.ContainsKey(key1)) - throw new ArgumentException("key2 exists in the dictionary but not key1"); - } - - Dictionary1[key1] = value; - Dictionary2[key2] = value; - - LLUDPClient[] oldArray = Array; - int oldLength = oldArray.Length; + int result = x.Address.Address.CompareTo(y.Address.Address); + if (result == 0) result = x.Port.CompareTo(y.Port); + return result; + } + } - LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; - for (int i = 0; i < oldLength; i++) - newArray[i] = oldArray[i]; - newArray[oldLength] = value; + #endregion IComparers - Array = newArray; - } + private ImmutableMap m_dict1; + private ImmutableMap m_dict2; + private LLUDPClient[] m_array; + public UDPClientCollection() + { + m_dict1 = new ImmutableMap(new UUIDComparer()); + m_dict2 = new ImmutableMap(new IPEndPointComparer()); + m_array = new LLUDPClient[0]; } - public bool Remove(UUID key1, IPEndPoint key2) + public void Add(UUID key1, IPEndPoint key2, LLUDPClient value) { - //rwLock.EnterWriteLock(); - - //try - //{ - // LLUDPClient value; - // if (Dictionary1.TryGetValue(key1, out value)) - // { - // Dictionary1.Remove(key1); - // Dictionary2.Remove(key2); + m_dict1 = m_dict1.Add(key1, value); + m_dict2 = m_dict2.Add(key2, value); + + // Copy the array by hand + LLUDPClient[] oldArray = m_array; + int oldLength = oldArray.Length; + LLUDPClient[] newArray = new LLUDPClient[oldLength + 1]; + + for (int i = 0; i < oldLength; i++) + newArray[i] = oldArray[i]; + newArray[oldLength] = value; + + m_array = newArray; + } - // LLUDPClient[] oldArray = Array; - // int oldLength = oldArray.Length; + public void Remove(UUID key1, IPEndPoint key2) + { + m_dict1 = m_dict1.Delete(key1); + m_dict2 = m_dict2.Delete(key2); - // LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; - // int j = 0; - // for (int i = 0; i < oldLength; i++) - // { - // if (oldArray[i] != value) - // newArray[j++] = oldArray[i]; - // } + LLUDPClient[] oldArray = m_array; + int oldLength = oldArray.Length; - // Array = newArray; - // return true; - // } - //} - //finally { rwLock.ExitWriteLock(); } + // Copy the array by hand - //return false; + LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; + int j = 0; - lock (m_sync) + for (int i = 0; i < oldLength; i++) { - LLUDPClient value; - if (Dictionary1.TryGetValue(key1, out value)) - { - Dictionary1.Remove(key1); - Dictionary2.Remove(key2); - - LLUDPClient[] oldArray = Array; - int oldLength = oldArray.Length; - - LLUDPClient[] newArray = new LLUDPClient[oldLength - 1]; - int j = 0; - for (int i = 0; i < oldLength; i++) - { - if (oldArray[i] != value) - newArray[j++] = oldArray[i]; - } - - Array = newArray; - return true; - } + if (oldArray[i].AgentID != key1) + newArray[j++] = oldArray[i]; } - return false; - + m_array = newArray; } public void Clear() { - //rwLock.EnterWriteLock(); - - //try - //{ - // Dictionary1.Clear(); - // Dictionary2.Clear(); - // Array = new LLUDPClient[0]; - //} - //finally { rwLock.ExitWriteLock(); } - - lock (m_sync) - { - Dictionary1.Clear(); - Dictionary2.Clear(); - Array = new LLUDPClient[0]; - } - + m_dict1 = new ImmutableMap(new UUIDComparer()); + m_dict2 = new ImmutableMap(new IPEndPointComparer()); + m_array = new LLUDPClient[0]; } public int Count { - get { return Array.Length; } + get { return m_array.Length; } } public bool ContainsKey(UUID key) { - return Dictionary1.ContainsKey(key); + return m_dict1.ContainsKey(key); } public bool ContainsKey(IPEndPoint key) { - return Dictionary2.ContainsKey(key); + return m_dict2.ContainsKey(key); } public bool TryGetValue(UUID key, out LLUDPClient value) { - ////bool success; - ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; - ////if (doLock) rwLock.EnterReadLock(); - - ////try { success = Dictionary1.TryGetValue(key, out value); } - ////finally { if (doLock) rwLock.ExitReadLock(); } - - ////return success; - - lock (m_sync) - return Dictionary1.TryGetValue(key, out value); - - //try - //{ - // return Dictionary1.TryGetValue(key, out value); - //} - //catch { } - //value = null; - //return false; + return m_dict1.TryGetValue(key, out value); } public bool TryGetValue(IPEndPoint key, out LLUDPClient value) { - ////bool success; - ////bool doLock = !rwLock.IsUpgradeableReadLockHeld; - ////if (doLock) rwLock.EnterReadLock(); - - ////try { success = Dictionary2.TryGetValue(key, out value); } - ////finally { if (doLock) rwLock.ExitReadLock(); } - - ////return success; - - lock (m_sync) - return Dictionary2.TryGetValue(key, out value); - - //try - //{ - // return Dictionary2.TryGetValue(key, out value); - //} - //catch { } - //value = null; - //return false; - + return m_dict2.TryGetValue(key, out value); } public void ForEach(Action action) { - //bool doLock = !rwLock.IsUpgradeableReadLockHeld; - //if (doLock) rwLock.EnterUpgradeableReadLock(); - - //try { Parallel.ForEach(Array, action); } - //finally { if (doLock) rwLock.ExitUpgradeableReadLock(); } - - LLUDPClient[] localArray = null; - lock (m_sync) - { - localArray = new LLUDPClient[Array.Length]; - Array.CopyTo(localArray, 0); - } - - Parallel.ForEach(localArray, action); - + Parallel.ForEach(m_array, action); } } } -- cgit v1.1