Fear the lockless LLUDP implementation!
parent
51ea39199b
commit
3a04d706c9
|
@ -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");
|
||||
// }
|
||||
// Copy the array by hand
|
||||
LLUDPClient[] oldArray = m_array;
|
||||
int oldLength = oldArray.Length;
|
||||
LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
|
||||
|
||||
// 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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.Physics.Manager"/>
|
||||
<Reference name="OpenSim.Services.Interfaces"/>
|
||||
<Reference name="BclExtras.dll"/>
|
||||
<Reference name="XMLRPC.dll"/>
|
||||
<Reference name="Nini.dll" />
|
||||
<Reference name="log4net.dll"/>
|
||||
|
|
Loading…
Reference in New Issue