diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/ClientManager.cs | 274 | ||||
-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 | 13 |
8 files changed, 290 insertions, 142 deletions
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index 094a3ff..61b59e7 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs | |||
@@ -28,193 +28,195 @@ | |||
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 OpenMetaverse; | 32 | using OpenMetaverse; |
33 | using OpenMetaverse.Packets; | 33 | using OpenMetaverse.Packets; |
34 | 34 | ||
35 | namespace OpenSim.Framework | 35 | namespace OpenSim.Framework |
36 | { | 36 | { |
37 | public delegate void ForEachClientDelegate(IClientAPI client); | 37 | /// <summary> |
38 | 38 | /// Maps from client AgentID and RemoteEndPoint values to IClientAPI | |
39 | /// references for all of the connected clients | ||
40 | /// </summary> | ||
39 | public class ClientManager | 41 | public class ClientManager |
40 | { | 42 | { |
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 43 | /// <summary>A dictionary mapping from <seealso cref="UUID"/> |
42 | 44 | /// to <seealso cref="IClientAPI"/> references</summary> | |
43 | private Dictionary<uint, IClientAPI> m_clients; | 45 | private Dictionary<UUID, IClientAPI> m_dict1; |
46 | /// <summary>A dictionary mapping from <seealso cref="IPEndPoint"/> | ||
47 | /// to <seealso cref="IClientAPI"/> references</summary> | ||
48 | private Dictionary<IPEndPoint, IClientAPI> m_dict2; | ||
49 | /// <summary>An immutable collection of <seealso cref="IClientAPI"/> | ||
50 | /// references</summary> | ||
51 | private IClientAPI[] m_array; | ||
52 | /// <summary>Synchronization object for writing to the collections</summary> | ||
53 | private object m_syncRoot = new object(); | ||
54 | |||
55 | /// <summary>Number of clients in the collection</summary> | ||
56 | public int Count { get { return m_dict1.Count; } } | ||
44 | 57 | ||
58 | /// <summary> | ||
59 | /// Default constructor | ||
60 | /// </summary> | ||
45 | public ClientManager() | 61 | public ClientManager() |
46 | { | 62 | { |
47 | m_clients = new Dictionary<uint, IClientAPI>(); | 63 | m_dict1 = new Dictionary<UUID, IClientAPI>(); |
64 | m_dict2 = new Dictionary<IPEndPoint, IClientAPI>(); | ||
65 | m_array = new IClientAPI[0]; | ||
48 | } | 66 | } |
49 | 67 | ||
50 | public void ForEachClient(ForEachClientDelegate whatToDo) | 68 | /// <summary> |
69 | /// Add a client reference to the collection if it does not already | ||
70 | /// exist | ||
71 | /// </summary> | ||
72 | /// <param name="value">Reference to the client object</param> | ||
73 | /// <returns>True if the client reference was successfully added, | ||
74 | /// otherwise false if the given key already existed in the collection</returns> | ||
75 | public bool Add(IClientAPI value) | ||
51 | { | 76 | { |
52 | IClientAPI[] LocalClients; | 77 | lock (m_syncRoot) |
53 | lock (m_clients) | ||
54 | { | 78 | { |
55 | LocalClients = new IClientAPI[m_clients.Count]; | 79 | if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint)) |
56 | m_clients.Values.CopyTo(LocalClients, 0); | 80 | return false; |
57 | } | ||
58 | 81 | ||
59 | for (int i = 0; i < LocalClients.Length; i++) | 82 | m_dict1[value.AgentId] = value; |
60 | { | 83 | m_dict2[value.RemoteEndPoint] = value; |
61 | try | ||
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 | } | ||
70 | } | ||
71 | 84 | ||
72 | public void Remove(uint id) | 85 | IClientAPI[] oldArray = m_array; |
73 | { | 86 | int oldLength = oldArray.Length; |
74 | lock (m_clients) | ||
75 | { | ||
76 | m_clients.Remove(id); | ||
77 | } | ||
78 | } | ||
79 | 87 | ||
80 | public void Add(uint id, IClientAPI client) | 88 | IClientAPI[] newArray = new IClientAPI[oldLength + 1]; |
81 | { | 89 | for (int i = 0; i < oldLength; i++) |
82 | lock (m_clients) | 90 | newArray[i] = oldArray[i]; |
83 | { | 91 | newArray[oldLength] = value; |
84 | m_clients.Add(id, client); | 92 | |
93 | m_array = newArray; | ||
85 | } | 94 | } |
95 | |||
96 | return true; | ||
86 | } | 97 | } |
87 | 98 | ||
88 | /// <summary> | 99 | /// <summary> |
89 | /// Pass incoming packet to client. | 100 | /// Remove a client from the collection |
90 | /// </summary> | 101 | /// </summary> |
91 | /// <param name="circuitCode">uint identifying the connection/client.</param> | 102 | /// <param name="key">UUID of the client to remove</param> |
92 | /// <param name="packet">object containing the packet.</param> | 103 | /// <returns>True if a client was removed, or false if the given UUID |
93 | public void InPacket(uint circuitCode, object packet) | 104 | /// was not present in the collection</returns> |
94 | { | 105 | public bool Remove(UUID key) |
95 | IClientAPI client; | ||
96 | bool tryGetRet = false; | ||
97 | |||
98 | lock (m_clients) | ||
99 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | ||
100 | |||
101 | if (tryGetRet) | ||
102 | { | ||
103 | client.InPacket(packet); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | public void CloseAllAgents(uint circuitCode) | ||
108 | { | 106 | { |
109 | IClientAPI client; | 107 | lock (m_syncRoot) |
110 | bool tryGetRet = false; | ||
111 | lock (m_clients) | ||
112 | tryGetRet = m_clients.TryGetValue(circuitCode, out client); | ||
113 | if (tryGetRet) | ||
114 | { | 108 | { |
115 | CloseAllCircuits(client.AgentId); | 109 | IClientAPI value; |
116 | } | 110 | if (m_dict1.TryGetValue(key, out value)) |
117 | } | 111 | { |
112 | m_dict1.Remove(key); | ||
113 | m_dict2.Remove(value.RemoteEndPoint); | ||
118 | 114 | ||
119 | public void CloseAllCircuits(UUID agentId) | 115 | IClientAPI[] oldArray = m_array; |
120 | { | 116 | int oldLength = oldArray.Length; |
121 | uint[] circuits = GetAllCircuits(agentId); | ||
122 | // We're using a for loop here so changes to the circuits don't cause it to completely fail. | ||
123 | 117 | ||
124 | for (int i = 0; i < circuits.Length; i++) | 118 | IClientAPI[] newArray = new IClientAPI[oldLength - 1]; |
125 | { | 119 | int j = 0; |
126 | IClientAPI client; | 120 | for (int i = 0; i < oldLength; i++) |
127 | try | ||
128 | { | ||
129 | bool tryGetRet = false; | ||
130 | lock (m_clients) | ||
131 | tryGetRet = m_clients.TryGetValue(circuits[i], out client); | ||
132 | if (tryGetRet) | ||
133 | { | 121 | { |
134 | Remove(client.CircuitCode); | 122 | if (oldArray[i] != value) |
135 | client.Close(false); | 123 | newArray[j++] = oldArray[i]; |
136 | } | 124 | } |
137 | } | 125 | |
138 | catch (Exception e) | 126 | m_array = newArray; |
139 | { | 127 | return true; |
140 | m_log.Error(string.Format("[CLIENT]: Unable to shutdown circuit for: {0}\n Reason: {1}", agentId, e)); | ||
141 | } | 128 | } |
142 | } | 129 | } |
130 | |||
131 | return false; | ||
143 | } | 132 | } |
144 | 133 | ||
145 | // [Obsolete("Using Obsolete to drive development is invalid. Obsolete presumes that something new has already been created to replace this.")] | 134 | /// <summary> |
146 | public uint[] GetAllCircuits(UUID agentId) | 135 | /// Resets the client collection |
136 | /// </summary> | ||
137 | public void Clear() | ||
147 | { | 138 | { |
148 | List<uint> circuits = new List<uint>(); | 139 | lock (m_syncRoot) |
149 | // Wasteful, I know | ||
150 | IClientAPI[] LocalClients = new IClientAPI[0]; | ||
151 | lock (m_clients) | ||
152 | { | 140 | { |
153 | LocalClients = new IClientAPI[m_clients.Count]; | 141 | m_dict1.Clear(); |
154 | m_clients.Values.CopyTo(LocalClients, 0); | 142 | m_dict2.Clear(); |
143 | m_array = new IClientAPI[0]; | ||
155 | } | 144 | } |
156 | |||
157 | for (int i = 0; i < LocalClients.Length; i++) | ||
158 | { | ||
159 | if (LocalClients[i].AgentId == agentId) | ||
160 | { | ||
161 | circuits.Add(LocalClients[i].CircuitCode); | ||
162 | } | ||
163 | } | ||
164 | return circuits.ToArray(); | ||
165 | } | 145 | } |
166 | 146 | ||
167 | public List<uint> GetAllCircuitCodes() | 147 | /// <summary> |
148 | /// Checks if a UUID is in the collection | ||
149 | /// </summary> | ||
150 | /// <param name="key">UUID to check for</param> | ||
151 | /// <returns>True if the UUID was found in the collection, otherwise false</returns> | ||
152 | public bool ContainsKey(UUID key) | ||
168 | { | 153 | { |
169 | List<uint> circuits; | 154 | return m_dict1.ContainsKey(key); |
170 | 155 | } | |
171 | lock (m_clients) | ||
172 | { | ||
173 | circuits = new List<uint>(m_clients.Keys); | ||
174 | } | ||
175 | 156 | ||
176 | return circuits; | 157 | /// <summary> |
158 | /// Checks if an endpoint is in the collection | ||
159 | /// </summary> | ||
160 | /// <param name="key">Endpoint to check for</param> | ||
161 | /// <returns>True if the endpoint was found in the collection, otherwise false</returns> | ||
162 | public bool ContainsKey(IPEndPoint key) | ||
163 | { | ||
164 | return m_dict2.ContainsKey(key); | ||
177 | } | 165 | } |
178 | 166 | ||
179 | public void ViewerEffectHandler(IClientAPI sender, List<ViewerEffectEventHandlerArg> args) | 167 | /// <summary> |
168 | /// Attempts to fetch a value out of the collection | ||
169 | /// </summary> | ||
170 | /// <param name="key">UUID of the client to retrieve</param> | ||
171 | /// <param name="value">Retrieved client, or null on lookup failure</param> | ||
172 | /// <returns>True if the lookup succeeded, otherwise false</returns> | ||
173 | public bool TryGetValue(UUID key, out IClientAPI value) | ||
180 | { | 174 | { |
181 | // TODO: don't create new blocks if recycling an old packet | 175 | try { return m_dict1.TryGetValue(key, out value); } |
182 | List<ViewerEffectPacket.EffectBlock> effectBlock = new List<ViewerEffectPacket.EffectBlock>(); | 176 | catch (Exception) |
183 | for (int i = 0; i < args.Count; i++) | ||
184 | { | 177 | { |
185 | ViewerEffectPacket.EffectBlock effect = new ViewerEffectPacket.EffectBlock(); | 178 | value = null; |
186 | effect.AgentID = args[i].AgentID; | 179 | return false; |
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 | } | 180 | } |
194 | ViewerEffectPacket.EffectBlock[] effectBlockArray = effectBlock.ToArray(); | 181 | } |
195 | 182 | ||
196 | IClientAPI[] LocalClients; | 183 | /// <summary> |
197 | lock (m_clients) | 184 | /// Attempts to fetch a value out of the collection |
185 | /// </summary> | ||
186 | /// <param name="key">Endpoint of the client to retrieve</param> | ||
187 | /// <param name="value">Retrieved client, or null on lookup failure</param> | ||
188 | /// <returns>True if the lookup succeeded, otherwise false</returns> | ||
189 | public bool TryGetValue(IPEndPoint key, out IClientAPI value) | ||
190 | { | ||
191 | try { return m_dict2.TryGetValue(key, out value); } | ||
192 | catch (Exception) | ||
198 | { | 193 | { |
199 | LocalClients = new IClientAPI[m_clients.Count]; | 194 | value = null; |
200 | m_clients.Values.CopyTo(LocalClients, 0); | 195 | return false; |
201 | } | 196 | } |
197 | } | ||
202 | 198 | ||
203 | for (int i = 0; i < LocalClients.Length; i++) | 199 | /// <summary> |
204 | { | 200 | /// Performs a given task in parallel for each of the elements in the |
205 | if (LocalClients[i].AgentId != sender.AgentId) | 201 | /// collection |
206 | { | 202 | /// </summary> |
207 | LocalClients[i].SendViewerEffect(effectBlockArray); | 203 | /// <param name="action">Action to perform on each element</param> |
208 | } | 204 | public void ForEach(Action<IClientAPI> action) |
209 | } | 205 | { |
206 | IClientAPI[] localArray = m_array; | ||
207 | Parallel.ForEach<IClientAPI>(localArray, action); | ||
210 | } | 208 | } |
211 | 209 | ||
212 | public bool TryGetClient(uint circuitId, out IClientAPI user) | 210 | /// <summary> |
211 | /// Performs a given task synchronously for each of the elements in | ||
212 | /// the collection | ||
213 | /// </summary> | ||
214 | /// <param name="action">Action to perform on each element</param> | ||
215 | public void ForEachSync(Action<IClientAPI> action) | ||
213 | { | 216 | { |
214 | lock (m_clients) | 217 | IClientAPI[] localArray = m_array; |
215 | { | 218 | for (int i = 0; i < localArray.Length; i++) |
216 | return m_clients.TryGetValue(circuitId, out user); | 219 | action(localArray[i]); |
217 | } | ||
218 | } | 220 | } |
219 | } | 221 | } |
220 | } | 222 | } |
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..e21ff32 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs | |||
@@ -31,13 +31,24 @@ 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, |
44 | /// <summary>Any packets that do not fit into the other throttles</summary> | ||
39 | Task = 4, | 45 | Task = 4, |
46 | /// <summary>Texture assets</summary> | ||
40 | Texture = 5, | 47 | Texture = 5, |
48 | /// <summary>Non-texture assets</summary> | ||
41 | Asset = 6, | 49 | Asset = 6, |
50 | /// <summary>Avatar and primitive data</summary> | ||
51 | /// <remarks>This is a sub-category of Task</remarks> | ||
52 | State = 7, | ||
42 | } | 53 | } |
43 | } | 54 | } |