Fear the lockless LLUDP implementation!
parent
51ea39199b
commit
3a04d706c9
|
@ -30,6 +30,7 @@ using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
using BclExtras.Collections;
|
||||||
|
|
||||||
using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
|
using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
|
||||||
|
|
||||||
|
@ -37,246 +38,113 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
public sealed class UDPClientCollection
|
public sealed class UDPClientCollection
|
||||||
{
|
{
|
||||||
Dictionary<UUID, LLUDPClient> Dictionary1;
|
#region IComparers
|
||||||
Dictionary<IPEndPoint, LLUDPClient> Dictionary2;
|
|
||||||
LLUDPClient[] Array;
|
private sealed class UUIDComparer : IComparer<UUID>
|
||||||
ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl();
|
{
|
||||||
object m_sync = new object();
|
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()
|
public UDPClientCollection()
|
||||||
{
|
{
|
||||||
Dictionary1 = new Dictionary<UUID, LLUDPClient>();
|
m_dict1 = new ImmutableMap<UUID, LLUDPClient>(new UUIDComparer());
|
||||||
Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>();
|
m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
|
||||||
Array = new LLUDPClient[0];
|
m_array = new LLUDPClient[0];
|
||||||
}
|
|
||||||
|
|
||||||
public UDPClientCollection(int capacity)
|
|
||||||
{
|
|
||||||
Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity);
|
|
||||||
Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity);
|
|
||||||
Array = new LLUDPClient[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(UUID key1, IPEndPoint key2, LLUDPClient value)
|
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
|
// Copy the array by hand
|
||||||
//{
|
LLUDPClient[] oldArray = m_array;
|
||||||
// if (Dictionary1.ContainsKey(key1))
|
int oldLength = oldArray.Length;
|
||||||
// {
|
LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
|
||||||
// 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;
|
for (int i = 0; i < oldLength; i++)
|
||||||
// Dictionary2[key2] = value;
|
newArray[i] = oldArray[i];
|
||||||
|
newArray[oldLength] = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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[] oldArray = m_array;
|
||||||
//{
|
int oldLength = oldArray.Length;
|
||||||
// LLUDPClient value;
|
|
||||||
// if (Dictionary1.TryGetValue(key1, out value))
|
|
||||||
// {
|
|
||||||
// Dictionary1.Remove(key1);
|
|
||||||
// Dictionary2.Remove(key2);
|
|
||||||
|
|
||||||
// LLUDPClient[] oldArray = Array;
|
// Copy the array by hand
|
||||||
// int oldLength = oldArray.Length;
|
|
||||||
|
|
||||||
// LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
|
LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
|
||||||
// int j = 0;
|
int j = 0;
|
||||||
// for (int i = 0; i < oldLength; i++)
|
|
||||||
// {
|
|
||||||
// if (oldArray[i] != value)
|
|
||||||
// newArray[j++] = oldArray[i];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Array = newArray;
|
for (int i = 0; i < oldLength; i++)
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//finally { rwLock.ExitWriteLock(); }
|
|
||||||
|
|
||||||
//return false;
|
|
||||||
|
|
||||||
lock (m_sync)
|
|
||||||
{
|
{
|
||||||
LLUDPClient value;
|
if (oldArray[i].AgentID != key1)
|
||||||
if (Dictionary1.TryGetValue(key1, out value))
|
newArray[j++] = oldArray[i];
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
m_array = newArray;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
//rwLock.EnterWriteLock();
|
m_dict1 = new ImmutableMap<UUID, LLUDPClient>(new UUIDComparer());
|
||||||
|
m_dict2 = new ImmutableMap<IPEndPoint, LLUDPClient>(new IPEndPointComparer());
|
||||||
//try
|
m_array = new LLUDPClient[0];
|
||||||
//{
|
|
||||||
// Dictionary1.Clear();
|
|
||||||
// Dictionary2.Clear();
|
|
||||||
// Array = new LLUDPClient[0];
|
|
||||||
//}
|
|
||||||
//finally { rwLock.ExitWriteLock(); }
|
|
||||||
|
|
||||||
lock (m_sync)
|
|
||||||
{
|
|
||||||
Dictionary1.Clear();
|
|
||||||
Dictionary2.Clear();
|
|
||||||
Array = new LLUDPClient[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count
|
public int Count
|
||||||
{
|
{
|
||||||
get { return Array.Length; }
|
get { return m_array.Length; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(UUID key)
|
public bool ContainsKey(UUID key)
|
||||||
{
|
{
|
||||||
return Dictionary1.ContainsKey(key);
|
return m_dict1.ContainsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsKey(IPEndPoint key)
|
public bool ContainsKey(IPEndPoint key)
|
||||||
{
|
{
|
||||||
return Dictionary2.ContainsKey(key);
|
return m_dict2.ContainsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(UUID key, out LLUDPClient value)
|
public bool TryGetValue(UUID key, out LLUDPClient value)
|
||||||
{
|
{
|
||||||
////bool success;
|
return m_dict1.TryGetValue(key, out value);
|
||||||
////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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
|
public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
|
||||||
{
|
{
|
||||||
////bool success;
|
return m_dict2.TryGetValue(key, out value);
|
||||||
////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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ForEach(Action<LLUDPClient> action)
|
public void ForEach(Action<LLUDPClient> action)
|
||||||
{
|
{
|
||||||
//bool doLock = !rwLock.IsUpgradeableReadLockHeld;
|
Parallel.ForEach<LLUDPClient>(m_array, action);
|
||||||
//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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
|
@ -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.
|
Binary file not shown.
|
@ -1767,6 +1767,7 @@
|
||||||
<Reference name="OpenSim.Region.Communications.Local"/>
|
<Reference name="OpenSim.Region.Communications.Local"/>
|
||||||
<Reference name="OpenSim.Region.Physics.Manager"/>
|
<Reference name="OpenSim.Region.Physics.Manager"/>
|
||||||
<Reference name="OpenSim.Services.Interfaces"/>
|
<Reference name="OpenSim.Services.Interfaces"/>
|
||||||
|
<Reference name="BclExtras.dll"/>
|
||||||
<Reference name="XMLRPC.dll"/>
|
<Reference name="XMLRPC.dll"/>
|
||||||
<Reference name="Nini.dll" />
|
<Reference name="Nini.dll" />
|
||||||
<Reference name="log4net.dll"/>
|
<Reference name="log4net.dll"/>
|
||||||
|
|
Loading…
Reference in New Issue