diff options
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r-- | OpenSim/Framework/ClientManager.cs | 258 | ||||
-rw-r--r-- | OpenSim/Framework/Communications/GenericAsyncResult.cs | 1 | ||||
-rw-r--r-- | OpenSim/Framework/Communications/RestClient.cs | 6 | ||||
-rw-r--r-- | OpenSim/Framework/IClientAPI.cs | 4 | ||||
-rw-r--r-- | OpenSim/Framework/IScene.cs | 1 | ||||
-rw-r--r-- | OpenSim/Framework/LocklessQueue.cs | 130 | ||||
-rw-r--r-- | OpenSim/Framework/Parallel.cs | 3 | ||||
-rw-r--r-- | OpenSim/Framework/ThrottleOutPacketType.cs | 18 |
8 files changed, 278 insertions, 143 deletions
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index 094a3ff..367bc6a 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs | |||
@@ -28,193 +28,183 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using log4net; | 31 | using System.Net; |
32 | using BclExtras.Collections; | ||
32 | using OpenMetaverse; | 33 | using OpenMetaverse; |
33 | using OpenMetaverse.Packets; | 34 | using OpenMetaverse.Packets; |
34 | 35 | ||
35 | namespace OpenSim.Framework | 36 | namespace OpenSim.Framework |
36 | { | 37 | { |
37 | public delegate void ForEachClientDelegate(IClientAPI client); | 38 | /// <summary> |
38 | 39 | /// Maps from client AgentID and RemoteEndPoint values to IClientAPI | |
40 | /// references for all of the connected clients | ||
41 | /// </summary> | ||
39 | public class ClientManager | 42 | public class ClientManager |
40 | { | 43 | { |
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | #region IComparers |
42 | |||
43 | private Dictionary<uint, IClientAPI> m_clients; | ||
44 | 45 | ||
45 | public ClientManager() | 46 | private sealed class UUIDComparer : IComparer<UUID> |
46 | { | 47 | { |
47 | m_clients = new Dictionary<uint, IClientAPI>(); | 48 | public int Compare(UUID x, UUID y) |
48 | } | ||
49 | |||
50 | public void ForEachClient(ForEachClientDelegate whatToDo) | ||
51 | { | ||
52 | IClientAPI[] LocalClients; | ||
53 | lock (m_clients) | ||
54 | { | ||
55 | LocalClients = new IClientAPI[m_clients.Count]; | ||
56 | m_clients.Values.CopyTo(LocalClients, 0); | ||
57 | } | ||
58 | |||
59 | for (int i = 0; i < LocalClients.Length; i++) | ||
60 | { | 49 | { |
61 | try | 50 | return x.CompareTo(y); |
62 | { | ||
63 | whatToDo(LocalClients[i]); | ||
64 | } | ||
65 | catch (Exception e) | ||
66 | { | ||
67 | m_log.Warn("[CLIENT]: Unable to do ForEachClient for one of the clients" + "\n Reason: " + e.ToString()); | ||
68 | } | ||
69 | } | 51 | } |
70 | } | 52 | } |
71 | 53 | ||
72 | public void Remove(uint id) | 54 | private sealed class IPEndPointComparer : IComparer<IPEndPoint> |
73 | { | 55 | { |
74 | lock (m_clients) | 56 | public int Compare(IPEndPoint x, IPEndPoint y) |
75 | { | 57 | { |
76 | m_clients.Remove(id); | 58 | if (x == null && y == null) |
77 | } | 59 | return 0; |
78 | } | 60 | else if (x == null) |
61 | return -1; | ||
62 | else if (y == null) | ||
63 | return 1; | ||
79 | 64 | ||
80 | public void Add(uint id, IClientAPI client) | 65 | int result = x.Address.Address.CompareTo(y.Address.Address); |
81 | { | 66 | if (result == 0) result = x.Port.CompareTo(y.Port); |
82 | lock (m_clients) | 67 | |
83 | { | 68 | return result; |
84 | m_clients.Add(id, client); | ||
85 | } | 69 | } |
86 | } | 70 | } |
87 | 71 | ||
72 | #endregion IComparers | ||
73 | |||
74 | /// <summary>An immutable dictionary mapping from <seealso cref="UUID"/> | ||
75 | /// to <seealso cref="IClientAPI"/> references</summary> | ||
76 | private ImmutableMap<UUID, IClientAPI> m_dict; | ||
77 | /// <summary>An immutable dictionary mapping from <seealso cref="IPEndPoint"/> | ||
78 | /// to <seealso cref="IClientAPI"/> references</summary> | ||
79 | private ImmutableMap<IPEndPoint, IClientAPI> m_dict2; | ||
80 | /// <summary>Immutability grants thread safety for concurrent reads and | ||
81 | /// read-writes, but not concurrent writes</summary> | ||
82 | private object m_writeLock = new object(); | ||
83 | |||
84 | /// <summary>Number of clients in the collection</summary> | ||
85 | public int Count { get { return m_dict.Count; } } | ||
86 | |||
88 | /// <summary> | 87 | /// <summary> |
89 | /// Pass incoming packet to client. | 88 | /// Default constructor |
90 | /// </summary> | 89 | /// </summary> |
91 | /// <param name="circuitCode">uint identifying the connection/client.</param> | 90 | public ClientManager() |
92 | /// <param name="packet">object containing the packet.</param> | ||
93 | public void InPacket(uint circuitCode, object packet) | ||
94 | { | 91 | { |
95 | IClientAPI client; | 92 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); |
96 | bool tryGetRet = false; | 93 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); |
97 | |||
98 | lock (m_clients) | ||
99 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | ||
100 | |||
101 | if (tryGetRet) | ||
102 | { | ||
103 | client.InPacket(packet); | ||
104 | } | ||
105 | } | 94 | } |
106 | 95 | ||
107 | public void CloseAllAgents(uint circuitCode) | 96 | /// <summary> |
108 | { | 97 | /// Add a client reference to the collection if it does not already |
109 | IClientAPI client; | 98 | /// exist |
110 | bool tryGetRet = false; | 99 | /// </summary> |
111 | lock (m_clients) | 100 | /// <param name="value">Reference to the client object</param> |
112 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | 101 | /// <returns>True if the client reference was successfully added, |
113 | if (tryGetRet) | 102 | /// otherwise false if the given key already existed in the collection</returns> |
114 | { | 103 | public bool Add(IClientAPI value) |
115 | CloseAllCircuits(client.AgentId); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | public void CloseAllCircuits(UUID agentId) | ||
120 | { | 104 | { |
121 | uint[] circuits = GetAllCircuits(agentId); | 105 | lock (m_writeLock) |
122 | // We're using a for loop here so changes to the circuits don't cause it to completely fail. | ||
123 | |||
124 | for (int i = 0; i < circuits.Length; i++) | ||
125 | { | 106 | { |
126 | IClientAPI client; | 107 | if (!m_dict.ContainsKey(value.AgentId) && !m_dict2.ContainsKey(value.RemoteEndPoint)) |
127 | try | ||
128 | { | 108 | { |
129 | bool tryGetRet = false; | 109 | m_dict = m_dict.Add(value.AgentId, value); |
130 | lock (m_clients) | 110 | m_dict2 = m_dict2.Add(value.RemoteEndPoint, value); |
131 | tryGetRet = m_clients.TryGetValue(circuits[i], out client); | 111 | |
132 | if (tryGetRet) | 112 | return true; |
133 | { | ||
134 | Remove(client.CircuitCode); | ||
135 | client.Close(false); | ||
136 | } | ||
137 | } | 113 | } |
138 | catch (Exception e) | 114 | else |
139 | { | 115 | { |
140 | m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e)); | 116 | return false; |
141 | } | 117 | } |
142 | } | 118 | } |
143 | } | 119 | } |
144 | 120 | ||
145 | // [Obsolete("Using Obsolete to drive development is invalid. Obsolete presumes that something new has already been created to replace this.")] | 121 | /// <summary> |
146 | public uint[] GetAllCircuits(UUID agentId) | 122 | /// Remove a client from the collection |
123 | /// </summary> | ||
124 | /// <param name="key">UUID of the client to remove</param> | ||
125 | /// <returns>True if a client was removed, or false if the given UUID | ||
126 | /// was not present in the collection</returns> | ||
127 | public bool Remove(UUID key) | ||
147 | { | 128 | { |
148 | List<uint> circuits = new List<uint>(); | 129 | lock (m_writeLock) |
149 | // Wasteful, I know | ||
150 | IClientAPI[] LocalClients = new IClientAPI[0]; | ||
151 | lock (m_clients) | ||
152 | { | 130 | { |
153 | LocalClients = new IClientAPI[m_clients.Count]; | 131 | IClientAPI client; |
154 | m_clients.Values.CopyTo(LocalClients, 0); | ||
155 | } | ||
156 | 132 | ||
157 | for (int i = 0; i < LocalClients.Length; i++) | 133 | if (m_dict.TryGetValue(key, out client)) |
158 | { | ||
159 | if (LocalClients[i].AgentId == agentId) | ||
160 | { | 134 | { |
161 | circuits.Add(LocalClients[i].CircuitCode); | 135 | m_dict = m_dict.Delete(key); |
136 | m_dict2 = m_dict2.Delete(client.RemoteEndPoint); | ||
137 | return true; | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | return false; | ||
162 | } | 142 | } |
163 | } | 143 | } |
164 | return circuits.ToArray(); | ||
165 | } | 144 | } |
166 | 145 | ||
167 | public List<uint> GetAllCircuitCodes() | 146 | /// <summary> |
147 | /// Resets the client collection | ||
148 | /// </summary> | ||
149 | public void Clear() | ||
168 | { | 150 | { |
169 | List<uint> circuits; | 151 | lock (m_writeLock) |
170 | |||
171 | lock (m_clients) | ||
172 | { | 152 | { |
173 | circuits = new List<uint>(m_clients.Keys); | 153 | m_dict = new ImmutableMap<UUID, IClientAPI>(new UUIDComparer()); |
154 | m_dict2 = new ImmutableMap<IPEndPoint, IClientAPI>(new IPEndPointComparer()); | ||
174 | } | 155 | } |
156 | } | ||
175 | 157 | ||
176 | return circuits; | 158 | /// <summary> |
159 | /// Checks if a UUID is in the collection | ||
160 | /// </summary> | ||
161 | /// <param name="key">UUID to check for</param> | ||
162 | /// <returns>True if the UUID was found in the collection, otherwise false</returns> | ||
163 | public bool ContainsKey(UUID key) | ||
164 | { | ||
165 | return m_dict.ContainsKey(key); | ||
177 | } | 166 | } |
178 | 167 | ||
179 | public void ViewerEffectHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args) | 168 | /// <summary> |
169 | /// Checks if an endpoint is in the collection | ||
170 | /// </summary> | ||
171 | /// <param name="key">Endpoint to check for</param> | ||
172 | /// <returns>True if the endpoint was found in the collection, otherwise false</returns> | ||
173 | public bool ContainsKey(IPEndPoint key) | ||
180 | { | 174 | { |
181 | // TODO: don't create new blocks if recycling an old packet | 175 | return m_dict2.ContainsKey(key); |
182 | List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); | 176 | } |
183 | for (int i = 0; i < args.Count; i++) | ||
184 | { | ||
185 | ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock(); | ||
186 | effect.AgentID = args[i].AgentID; | ||
187 | effect.Color = args[i].Color; | ||
188 | effect.Duration = args[i].Duration; | ||
189 | effect.ID = args[i].ID; | ||
190 | effect.Type = args[i].Type; | ||
191 | effect.TypeData = args[i].TypeData; | ||
192 | effectBlock.Add(effect); | ||
193 | } | ||
194 | ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); | ||
195 | 177 | ||
196 | IClientAPI[] LocalClients; | 178 | /// <summary> |
197 | lock (m_clients) | 179 | /// Attempts to fetch a value out of the collection |
198 | { | 180 | /// </summary> |
199 | LocalClients = new IClientAPI[m_clients.Count]; | 181 | /// <param name="key">UUID of the client to retrieve</param> |
200 | m_clients.Values.CopyTo(LocalClients, 0); | 182 | /// <param name="value">Retrieved client, or null on lookup failure</param> |
201 | } | 183 | /// <returns>True if the lookup succeeded, otherwise false</returns> |
184 | public bool TryGetValue(UUID key, out IClientAPI value) | ||
185 | { | ||
186 | return m_dict.TryGetValue(key, out value); | ||
187 | } | ||
202 | 188 | ||
203 | for (int i = 0; i < LocalClients.Length; i++) | 189 | /// <summary> |
204 | { | 190 | /// Attempts to fetch a value out of the collection |
205 | if (LocalClients[i].AgentId != sender.AgentId) | 191 | /// </summary> |
206 | { | 192 | /// <param name="key">Endpoint of the client to retrieve</param> |
207 | LocalClients[i].SendViewerEffect(effectBlockArray); | 193 | /// <param name="value">Retrieved client, or null on lookup failure</param> |
208 | } | 194 | /// <returns>True if the lookup succeeded, otherwise false</returns> |
209 | } | 195 | public bool TryGetValue(IPEndPoint key, out IClientAPI value) |
196 | { | ||
197 | return m_dict2.TryGetValue(key, out value); | ||
210 | } | 198 | } |
211 | 199 | ||
212 | public bool TryGetClient(uint circuitId, out IClientAPI user) | 200 | /// <summary> |
201 | /// Performs a given task in parallel for each of the elements in the | ||
202 | /// collection | ||
203 | /// </summary> | ||
204 | /// <param name="action">Action to perform on each element</param> | ||
205 | public void ForEach(Action<IClientAPI> action) | ||
213 | { | 206 | { |
214 | lock (m_clients) | 207 | Parallel.ForEach<IClientAPI>(m_dict.Values, action); |
215 | { | ||
216 | return m_clients.TryGetValue(circuitId, out user); | ||
217 | } | ||
218 | } | 208 | } |
219 | } | 209 | } |
220 | } | 210 | } |
diff --git a/OpenSim/Framework/Communications/GenericAsyncResult.cs b/OpenSim/Framework/Communications/GenericAsyncResult.cs index efd2f43..8e3f62b 100644 --- a/OpenSim/Framework/Communications/GenericAsyncResult.cs +++ b/OpenSim/Framework/Communications/GenericAsyncResult.cs | |||
@@ -146,6 +146,7 @@ namespace OpenSim.Framework.Communications | |||
146 | // If the operation isn't done, wait for it | 146 | // If the operation isn't done, wait for it |
147 | AsyncWaitHandle.WaitOne(); | 147 | AsyncWaitHandle.WaitOne(); |
148 | AsyncWaitHandle.Close(); | 148 | AsyncWaitHandle.Close(); |
149 | m_waitHandle.Close(); | ||
149 | m_waitHandle = null; // Allow early GC | 150 | m_waitHandle = null; // Allow early GC |
150 | } | 151 | } |
151 | 152 | ||
diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index d98f47d..a74169e 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs | |||
@@ -105,7 +105,7 @@ namespace OpenSim.Framework.Communications | |||
105 | /// <summary> | 105 | /// <summary> |
106 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode | 106 | /// This flag will help block the main synchroneous method, in case we run in synchroneous mode |
107 | /// </summary> | 107 | /// </summary> |
108 | public static ManualResetEvent _allDone = new ManualResetEvent(false); | 108 | //public static ManualResetEvent _allDone = new ManualResetEvent(false); |
109 | 109 | ||
110 | /// <summary> | 110 | /// <summary> |
111 | /// Default time out period | 111 | /// Default time out period |
@@ -282,12 +282,12 @@ namespace OpenSim.Framework.Communications | |||
282 | else | 282 | else |
283 | { | 283 | { |
284 | s.Close(); | 284 | s.Close(); |
285 | _allDone.Set(); | 285 | //_allDone.Set(); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | catch (Exception e) | 288 | catch (Exception e) |
289 | { | 289 | { |
290 | _allDone.Set(); | 290 | //_allDone.Set(); |
291 | _asyncException = e; | 291 | _asyncException = e; |
292 | } | 292 | } |
293 | } | 293 | } |
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index d3bd9e7..29846f5 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs | |||
@@ -561,6 +561,8 @@ namespace OpenSim.Framework | |||
561 | // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] | 561 | // [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")] |
562 | uint CircuitCode { get; } | 562 | uint CircuitCode { get; } |
563 | 563 | ||
564 | IPEndPoint RemoteEndPoint { get; } | ||
565 | |||
564 | event GenericMessage OnGenericMessage; | 566 | event GenericMessage OnGenericMessage; |
565 | 567 | ||
566 | // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")] | 568 | // [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")] |
@@ -802,7 +804,7 @@ namespace OpenSim.Framework | |||
802 | 804 | ||
803 | void InPacket(object NewPack); | 805 | void InPacket(object NewPack); |
804 | void ProcessInPacket(Packet NewPack); | 806 | void ProcessInPacket(Packet NewPack); |
805 | void Close(bool ShutdownCircuit); | 807 | void Close(); |
806 | void Kick(string message); | 808 | void Kick(string message); |
807 | 809 | ||
808 | /// <summary> | 810 | /// <summary> |
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 489653f..f34027d 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs | |||
@@ -71,7 +71,6 @@ namespace OpenSim.Framework | |||
71 | 71 | ||
72 | void AddNewClient(IClientAPI client); | 72 | void AddNewClient(IClientAPI client); |
73 | void RemoveClient(UUID agentID); | 73 | void RemoveClient(UUID agentID); |
74 | void CloseAllAgents(uint circuitcode); | ||
75 | 74 | ||
76 | void Restart(int seconds); | 75 | void Restart(int seconds); |
77 | //RegionInfo OtherRegionUp(RegionInfo thisRegion); | 76 | //RegionInfo OtherRegionUp(RegionInfo thisRegion); |
diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs new file mode 100644 index 0000000..dd3d201 --- /dev/null +++ b/OpenSim/Framework/LocklessQueue.cs | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009, openmetaverse.org | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * - Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * | ||
8 | * - Redistributions of source code must retain the above copyright notice, this | ||
9 | * list of conditions and the following disclaimer. | ||
10 | * - Neither the name of the openmetaverse.org nor the names | ||
11 | * of its contributors may be used to endorse or promote products derived from | ||
12 | * this software without specific prior written permission. | ||
13 | * | ||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
24 | * POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | using System; | ||
28 | using System.Threading; | ||
29 | |||
30 | namespace OpenSim.Framework | ||
31 | { | ||
32 | public sealed class LocklessQueue<T> | ||
33 | { | ||
34 | private sealed class SingleLinkNode | ||
35 | { | ||
36 | public SingleLinkNode Next; | ||
37 | public T Item; | ||
38 | } | ||
39 | |||
40 | SingleLinkNode head; | ||
41 | SingleLinkNode tail; | ||
42 | int count; | ||
43 | |||
44 | public int Count { get { return count; } } | ||
45 | |||
46 | public LocklessQueue() | ||
47 | { | ||
48 | Init(); | ||
49 | } | ||
50 | |||
51 | public void Enqueue(T item) | ||
52 | { | ||
53 | SingleLinkNode oldTail = null; | ||
54 | SingleLinkNode oldTailNext; | ||
55 | |||
56 | SingleLinkNode newNode = new SingleLinkNode(); | ||
57 | newNode.Item = item; | ||
58 | |||
59 | bool newNodeWasAdded = false; | ||
60 | |||
61 | while (!newNodeWasAdded) | ||
62 | { | ||
63 | oldTail = tail; | ||
64 | oldTailNext = oldTail.Next; | ||
65 | |||
66 | if (tail == oldTail) | ||
67 | { | ||
68 | if (oldTailNext == null) | ||
69 | newNodeWasAdded = CAS(ref tail.Next, null, newNode); | ||
70 | else | ||
71 | CAS(ref tail, oldTail, oldTailNext); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | CAS(ref tail, oldTail, newNode); | ||
76 | Interlocked.Increment(ref count); | ||
77 | } | ||
78 | |||
79 | public bool Dequeue(out T item) | ||
80 | { | ||
81 | item = default(T); | ||
82 | SingleLinkNode oldHead = null; | ||
83 | bool haveAdvancedHead = false; | ||
84 | |||
85 | while (!haveAdvancedHead) | ||
86 | { | ||
87 | oldHead = head; | ||
88 | SingleLinkNode oldTail = tail; | ||
89 | SingleLinkNode oldHeadNext = oldHead.Next; | ||
90 | |||
91 | if (oldHead == head) | ||
92 | { | ||
93 | if (oldHead == oldTail) | ||
94 | { | ||
95 | if (oldHeadNext == null) | ||
96 | return false; | ||
97 | |||
98 | CAS(ref tail, oldTail, oldHeadNext); | ||
99 | } | ||
100 | else | ||
101 | { | ||
102 | item = oldHeadNext.Item; | ||
103 | haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | Interlocked.Decrement(ref count); | ||
109 | return true; | ||
110 | } | ||
111 | |||
112 | public void Clear() | ||
113 | { | ||
114 | Init(); | ||
115 | } | ||
116 | |||
117 | private void Init() | ||
118 | { | ||
119 | count = 0; | ||
120 | head = tail = new SingleLinkNode(); | ||
121 | } | ||
122 | |||
123 | private static bool CAS(ref SingleLinkNode location, SingleLinkNode comparand, SingleLinkNode newValue) | ||
124 | { | ||
125 | return | ||
126 | (object)comparand == | ||
127 | (object)Interlocked.CompareExchange<SingleLinkNode>(ref location, newValue, comparand); | ||
128 | } | ||
129 | } | ||
130 | } \ No newline at end of file | ||
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs index 74537ba..6efdad0 100644 --- a/OpenSim/Framework/Parallel.cs +++ b/OpenSim/Framework/Parallel.cs | |||
@@ -89,6 +89,7 @@ namespace OpenSim.Framework | |||
89 | } | 89 | } |
90 | 90 | ||
91 | threadFinishEvent.WaitOne(); | 91 | threadFinishEvent.WaitOne(); |
92 | threadFinishEvent.Close(); | ||
92 | 93 | ||
93 | if (exception != null) | 94 | if (exception != null) |
94 | throw new Exception(exception.Message, exception); | 95 | throw new Exception(exception.Message, exception); |
@@ -148,6 +149,7 @@ namespace OpenSim.Framework | |||
148 | } | 149 | } |
149 | 150 | ||
150 | threadFinishEvent.WaitOne(); | 151 | threadFinishEvent.WaitOne(); |
152 | threadFinishEvent.Close(); | ||
151 | 153 | ||
152 | if (exception != null) | 154 | if (exception != null) |
153 | throw new Exception(exception.Message, exception); | 155 | throw new Exception(exception.Message, exception); |
@@ -199,6 +201,7 @@ namespace OpenSim.Framework | |||
199 | } | 201 | } |
200 | 202 | ||
201 | threadFinishEvent.WaitOne(); | 203 | threadFinishEvent.WaitOne(); |
204 | threadFinishEvent.Close(); | ||
202 | 205 | ||
203 | if (exception != null) | 206 | if (exception != null) |
204 | throw new Exception(exception.Message, exception); | 207 | throw new Exception(exception.Message, exception); |
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index fd490a5..eb42fea 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs | |||
@@ -31,13 +31,23 @@ namespace OpenSim.Framework | |||
31 | { | 31 | { |
32 | public enum ThrottleOutPacketType : int | 32 | public enum ThrottleOutPacketType : int |
33 | { | 33 | { |
34 | Unknown = -1, // Also doubles as 'do not throttle' | 34 | /// <summary>Unthrottled packets</summary> |
35 | Unknown = -1, | ||
36 | /// <summary>Packets that are being resent</summary> | ||
35 | Resend = 0, | 37 | Resend = 0, |
38 | /// <summary>Terrain data</summary> | ||
36 | Land = 1, | 39 | Land = 1, |
40 | /// <summary>Wind data</summary> | ||
37 | Wind = 2, | 41 | Wind = 2, |
42 | /// <summary>Cloud data</summary> | ||
38 | Cloud = 3, | 43 | Cloud = 3, |
39 | Task = 4, | 44 | /// <summary>Texture assets</summary> |
40 | Texture = 5, | 45 | Texture = 4, |
41 | Asset = 6, | 46 | /// <summary>Non-texture assets</summary> |
47 | Asset = 5, | ||
48 | /// <summary>Avatar and primitive data</summary> | ||
49 | State = 6, | ||
50 | /// <summary>Any packets that do not fit into the other throttles</summary> | ||
51 | Task = 7, | ||
42 | } | 52 | } |
43 | } | 53 | } |