From a5b9971fd77c0c4bf70656be7f3e7999f59d9f85 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 9 Oct 2009 01:53:06 -0700 Subject: * Added a lock object for the write functions in LLUDPClientCollection (immutable != concurrent write safety) * Allow the UDP server to bind to a user-specified port again * Updated to a newer version of OpenSimUDPBase that streamlines the code even more. This also reintroduces the highly concurrent packet handling which needs more testing --- .../ClientStack/LindenUDP/LLUDPClientCollection.cs | 56 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs index abf3882..2222a33 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs @@ -36,6 +36,9 @@ using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim; namespace OpenSim.Region.ClientStack.LindenUDP { + /// + /// A thread safe mapping from endpoints to client references + /// public sealed class UDPClientCollection { #region IComparers @@ -52,43 +55,80 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion IComparers + /// An immutable dictionary mapping from + /// to references private ImmutableMap m_dict; + /// Immutability grants thread safety for concurrent reads and + /// read-writes, but not concurrent writes + private object m_writeLock; + /// Number of clients in the collection + public int Count { get { return m_dict.Count; } } + + /// + /// Default constructor + /// public UDPClientCollection() { m_dict = new ImmutableMap(new IPEndPointComparer()); } + /// + /// Add a client reference to the collection + /// + /// Remote endpoint of the client + /// Reference to the client object public void Add(IPEndPoint key, LLUDPClient value) { - m_dict = m_dict.Add(key, value); + lock (m_writeLock) + m_dict = m_dict.Add(key, value); } + /// + /// Remove a client from the collection + /// + /// Remote endpoint of the client public void Remove(IPEndPoint key) { - m_dict = m_dict.Delete(key); + lock (m_writeLock) + m_dict = m_dict.Delete(key); } + /// + /// Resets the client collection + /// public void Clear() { - m_dict = new ImmutableMap(new IPEndPointComparer()); - } - - public int Count - { - get { return m_dict.Count; } + lock (m_writeLock) + m_dict = new ImmutableMap(new IPEndPointComparer()); } + /// + /// Checks if an endpoint is in the collection + /// + /// Endpoint to check for + /// True if the endpoint was found in the collection, otherwise false public bool ContainsKey(IPEndPoint key) { return m_dict.ContainsKey(key); } + /// + /// Attempts to fetch a value out of the collection + /// + /// Endpoint of the client to retrieve + /// Retrieved client, or null on lookup failure + /// True if the lookup succeeded, otherwise false public bool TryGetValue(IPEndPoint key, out LLUDPClient value) { return m_dict.TryGetValue(key, out value); } + /// + /// Performs a given task in parallel for each of the elements in the + /// collection + /// + /// Action to perform on each element public void ForEach(Action action) { Parallel.ForEach(m_dict.Values, action); -- cgit v1.1