Fear the lockless LLUDP implementation!

prioritization
John Hurliman 2009-10-08 17:34:51 -07:00
parent 51ea39199b
commit 3a04d706c9
5 changed files with 150 additions and 193 deletions

View File

@ -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<UUID, LLUDPClient> Dictionary1;
Dictionary<IPEndPoint, LLUDPClient> Dictionary2;
LLUDPClient[] Array;
ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl();
object m_sync = new object();
#region IComparers
private sealed class UUIDComparer : IComparer<UUID>
{
public int Compare(UUID x, UUID y)
{
return x.Guid.CompareTo(y.Guid);
}
}
private sealed class IPEndPointComparer : IComparer<IPEndPoint>
{
public int Compare(IPEndPoint x, IPEndPoint y)
{
int result = x.Address.Address.CompareTo(y.Address.Address);
if (result == 0) result = x.Port.CompareTo(y.Port);
return result;
}
}
#endregion IComparers
private ImmutableMap<UUID, LLUDPClient> m_dict1;
private ImmutableMap<IPEndPoint, LLUDPClient> m_dict2;
private LLUDPClient[] m_array;
public UDPClientCollection()
{
Dictionary1 = new Dictionary<UUID, LLUDPClient>();
Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>();
Array = new LLUDPClient[0];
}
public UDPClientCollection(int capacity)
{
Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity);
Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity);
Array = new LLUDPClient[0];
m_dict1 = new ImmutableMap<UUID, LLUDPClient>(new UUIDComparer());
m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
m_array = new LLUDPClient[0];
}
public void Add(UUID key1, IPEndPoint key2, LLUDPClient value)
{
//rwLock.EnterWriteLock();
m_dict1 = m_dict1.Add(key1, value);
m_dict2 = m_dict2.Add(key2, value);
//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)
{
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;
}
// 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;
}
public bool Remove(UUID key1, IPEndPoint key2)
public void Remove(UUID key1, IPEndPoint key2)
{
//rwLock.EnterWriteLock();
m_dict1 = m_dict1.Delete(key1);
m_dict2 = m_dict2.Delete(key2);
//try
//{
// LLUDPClient value;
// if (Dictionary1.TryGetValue(key1, out value))
// {
// Dictionary1.Remove(key1);
// Dictionary2.Remove(key2);
LLUDPClient[] oldArray = m_array;
int oldLength = oldArray.Length;
// LLUDPClient[] oldArray = Array;
// int oldLength = oldArray.Length;
// Copy the array by hand
// 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[] newArray = new LLUDPClient[oldLength - 1];
int j = 0;
// Array = newArray;
// return true;
// }
//}
//finally { rwLock.ExitWriteLock(); }
//return false;
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<UUID, LLUDPClient>(new UUIDComparer());
m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(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<LLUDPClient> action)
{
//bool doLock = !rwLock.IsUpgradeableReadLockHeld;
//if (doLock) rwLock.EnterUpgradeableReadLock();
//try { Parallel.ForEach<LLUDPClient>(Array, action); }
//finally { if (doLock) rwLock.ExitUpgradeableReadLock(); }
LLUDPClient[] localArray = null;
lock (m_sync)
{
localArray = new LLUDPClient[Array.Length];
Array.CopyTo(localArray, 0);
}
Parallel.ForEach<LLUDPClient>(localArray, action);
Parallel.ForEach<LLUDPClient>(m_array, action);
}
}
}

View File

@ -0,0 +1,60 @@
MICROSOFT PUBLIC LICENSE (Ms-PL)
This license governs use of the accompanying software. If you use the software,
you accept this license. If you do not accept the license, do not use the
software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution"
have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the
software.
A "contributor" is any person that distributes its contribution under this
license.
"Licensed patents" are a contributor's patent claims that read directly on its
contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to
make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
its contribution in the software or derivative works of the contribution in the
software.
3. Conditions and Limitations
(A) No Trademark License- This license does not grant you rights to use any
contributors' name, logo, or trademarks.
(B) If you bring a patent claim against any contributor over patents that you
claim are infringed by the software, your patent license from such contributor
to the software ends automatically.
(C) If you distribute any portion of the software, you must retain all
copyright, patent, trademark, and attribution notices that are present in the
software.
(D) If you distribute any portion of the software in source code form, you may
do so only under this license by including a complete copy of this license with
your distribution. If you distribute any portion of the software in compiled or
object code form, you may only do so under a license that complies with this
license.
(E) The software is licensed "as-is." You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may have
additional consumer rights under your local laws which this license cannot
change. To the extent permitted under your local laws, the contributors exclude
the implied warranties of merchantability, fitness for a particular purpose and
non-infringement.

View File

@ -0,0 +1,28 @@
Copyright (c) 1999/2000 JJ2000 Partners.
This software module was originally developed by Raphaël Grosbois and
Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
Centre France S.A) in the course of development of the JPEG2000
standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
software module is an implementation of a part of the JPEG 2000
Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
Systems AB and Canon Research Centre France S.A (collectively JJ2000
Partners) agree not to assert against ISO/IEC and users of the JPEG
2000 Standard (Users) any of their rights under the copyright, not
including other intellectual property rights, for this software module
with respect to the usage by ISO/IEC and Users of this software module
or modifications thereof for use in hardware or software products
claiming conformance to the JPEG 2000 Standard. Those intending to use
this software module in hardware or software products are advised that
their use may infringe existing patents. The original developers of
this software module, JJ2000 Partners and ISO/IEC assume no liability
for use of this software module or modifications thereof. No license
or right to this software module is granted for non JPEG 2000 Standard
conforming products. JJ2000 Partners have full right to use this
software module for his/her own purpose, assign or donate this
software module to any third party and to inhibit third parties from
using this software module for non JPEG 2000 Standard conforming
products. This copyright notice must be included in all copies or
derivative works of this software module.

BIN
bin/BclExtras.dll Normal file

Binary file not shown.

View File

@ -1767,6 +1767,7 @@
<Reference name="OpenSim.Region.Communications.Local"/>
<Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="BclExtras.dll"/>
<Reference name="XMLRPC.dll"/>
<Reference name="Nini.dll" />
<Reference name="log4net.dll"/>