aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
diff options
context:
space:
mode:
authorTedd Hansen2008-01-12 14:30:22 +0000
committerTedd Hansen2008-01-12 14:30:22 +0000
commitbacbade369a5244f9bcc611488b59f3bd4c8a564 (patch)
tree2cd909eff401066a69dba96615cbf736fdd73be5 /OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
parent* Trying something to see if it helps teleports and border crossings (diff)
downloadopensim-SC_OLD-bacbade369a5244f9bcc611488b59f3bd4c8a564.zip
opensim-SC_OLD-bacbade369a5244f9bcc611488b59f3bd4c8a564.tar.gz
opensim-SC_OLD-bacbade369a5244f9bcc611488b59f3bd4c8a564.tar.bz2
opensim-SC_OLD-bacbade369a5244f9bcc611488b59f3bd4c8a564.tar.xz
Major reorganizing of DotNetEngine. Moved common script engine parts to ScriptEngine.Common, only .Net-specific code in DotNetEngine. AppDomains, event handling, event execution queue and multithreading, script load/unload queue, etc has been moved to ScriptEngine.Common.
Loads of things has been put into interfaces instead of the specific class. We are now one step closer to ScriptServer, and its very easy to implement new script languages. Just a few lines required to make them a OpenSim script module with all its glory.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs (renamed from OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs)725
1 files changed, 362 insertions, 363 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
index e7cb489..62194df 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs
@@ -1,364 +1,363 @@
1/* 1/*
2* Copyright (c) Contributors, http://opensimulator.org/ 2* Copyright (c) Contributors, http://opensimulator.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28/* Original code: Tedd Hansen */ 28/* Original code: Tedd Hansen */
29using System; 29using System;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Threading; 32using System.Threading;
33using libsecondlife; 33using libsecondlife;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Environment.Scenes.Scripting; 35using OpenSim.Region.Environment.Scenes.Scripting;
36using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; 36
37 37namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
38namespace OpenSim.Region.ScriptEngine.DotNetEngine 38{
39{ 39 /// <summary>
40 /// <summary> 40 /// EventQueueManager handles event queues
41 /// EventQueueManager handles event queues 41 /// Events are queued and executed in separate thread
42 /// Events are queued and executed in separate thread 42 /// </summary>
43 /// </summary> 43 [Serializable]
44 [Serializable] 44 public class EventQueueManager
45 internal class EventQueueManager 45 {
46 { 46
47 47 //
48 // 48 // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine".
49 // Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine". 49 //
50 // 50 // Class purpose is to queue and execute functions that are received by "EventManager":
51 // Class purpose is to queue and execute functions that are received by "EventManager": 51 // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution.
52 // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. 52 // - allowing us to prioritize and control execution of script functions.
53 // - allowing us to prioritize and control execution of script functions. 53 // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety.
54 // Class can use multiple threads for simultaneous execution. Mutexes are used for thread safety. 54 //
55 // 55 // 1. Hold an execution queue for scripts
56 // 1. Hold an execution queue for scripts 56 // 2. Use threads to process queue, each thread executes one script function on each pass.
57 // 2. Use threads to process queue, each thread executes one script function on each pass. 57 // 3. Catch any script error and process it
58 // 3. Catch any script error and process it 58 //
59 // 59 //
60 // 60 // Notes:
61 // Notes: 61 // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts.
62 // * Current execution load balancing is optimized for 1 thread, and can cause unfair execute balancing between scripts. 62 // Not noticeable unless server is under high load.
63 // Not noticeable unless server is under high load. 63 // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet,
64 // * This class contains the number of threads used for script executions. Since we are not microthreading scripts yet, 64 // increase number of threads to allow more concurrent script executions in OpenSim.
65 // increase number of threads to allow more concurrent script executions in OpenSim. 65 //
66 // 66
67 67
68 68 /// <summary>
69 /// <summary> 69 /// List of threads processing event queue
70 /// List of threads processing event queue 70 /// </summary>
71 /// </summary> 71 private List<Thread> eventQueueThreads = new List<Thread>();
72 private List<Thread> eventQueueThreads = new List<Thread>(); 72
73 73 private object queueLock = new object(); // Mutex lock object
74 private object queueLock = new object(); // Mutex lock object 74
75 75 /// <summary>
76 /// <summary> 76 /// How many ms to sleep if queue is empty
77 /// How many ms to sleep if queue is empty 77 /// </summary>
78 /// </summary> 78 private int nothingToDoSleepms = 50;
79 private int nothingToDoSleepms = 50; 79
80 80 /// <summary>
81 /// <summary> 81 /// How many threads to process queue with
82 /// How many threads to process queue with 82 /// </summary>
83 /// </summary> 83 private int numberOfThreads = 2;
84 private int numberOfThreads = 2; 84
85 85 /// <summary>
86 /// <summary> 86 /// Queue containing events waiting to be executed
87 /// Queue containing events waiting to be executed 87 /// </summary>
88 /// </summary> 88 private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>();
89 private Queue<QueueItemStruct> eventQueue = new Queue<QueueItemStruct>(); 89
90 90 /// <summary>
91 /// <summary> 91 /// Queue item structure
92 /// Queue item structure 92 /// </summary>
93 /// </summary> 93 private struct QueueItemStruct
94 private struct QueueItemStruct 94 {
95 { 95 public uint localID;
96 public uint localID; 96 public LLUUID itemID;
97 public LLUUID itemID; 97 public string functionName;
98 public string functionName; 98 public object[] param;
99 public object[] param; 99 }
100 } 100
101 101 /// <summary>
102 /// <summary> 102 /// List of localID locks for mutex processing of script events
103 /// List of localID locks for mutex processing of script events 103 /// </summary>
104 /// </summary> 104 private List<uint> objectLocks = new List<uint>();
105 private List<uint> objectLocks = new List<uint>(); 105
106 106 private object tryLockLock = new object(); // Mutex lock object
107 private object tryLockLock = new object(); // Mutex lock object 107
108 108 private ScriptEngine m_ScriptEngine;
109 private ScriptEngine m_ScriptEngine; 109
110 110 public EventQueueManager(ScriptEngine _ScriptEngine)
111 public EventQueueManager(ScriptEngine _ScriptEngine) 111 {
112 { 112 m_ScriptEngine = _ScriptEngine;
113 m_ScriptEngine = _ScriptEngine; 113
114 114 //
115 // 115 // Start event queue processing threads (worker threads)
116 // Start event queue processing threads (worker threads) 116 //
117 // 117 for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++)
118 for (int ThreadCount = 0; ThreadCount <= numberOfThreads; ThreadCount++) 118 {
119 { 119 Thread EventQueueThread = new Thread(EventQueueThreadLoop);
120 Thread EventQueueThread = new Thread(EventQueueThreadLoop); 120 eventQueueThreads.Add(EventQueueThread);
121 eventQueueThreads.Add(EventQueueThread); 121 EventQueueThread.IsBackground = true;
122 EventQueueThread.IsBackground = true; 122 EventQueueThread.Priority = ThreadPriority.BelowNormal;
123 EventQueueThread.Priority = ThreadPriority.BelowNormal; 123 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
124 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; 124 EventQueueThread.Start();
125 EventQueueThread.Start(); 125 }
126 } 126 }
127 } 127
128 128 ~EventQueueManager()
129 ~EventQueueManager() 129 {
130 { 130 // Kill worker threads
131 // Kill worker threads 131 foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads))
132 foreach (Thread EventQueueThread in new ArrayList(eventQueueThreads)) 132 {
133 { 133 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
134 if (EventQueueThread != null && EventQueueThread.IsAlive == true) 134 {
135 { 135 try
136 try 136 {
137 { 137 EventQueueThread.Abort();
138 EventQueueThread.Abort(); 138 EventQueueThread.Join();
139 EventQueueThread.Join(); 139 }
140 } 140 catch (Exception)
141 catch (Exception) 141 {
142 { 142 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
143 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); 143 }
144 } 144 }
145 } 145 }
146 } 146 eventQueueThreads.Clear();
147 eventQueueThreads.Clear(); 147 // Todo: Clean up our queues
148 // Todo: Clean up our queues 148 eventQueue.Clear();
149 eventQueue.Clear(); 149 }
150 } 150
151 151 /// <summary>
152 /// <summary> 152 /// Queue processing thread loop
153 /// Queue processing thread loop 153 /// </summary>
154 /// </summary> 154 private void EventQueueThreadLoop()
155 private void EventQueueThreadLoop() 155 {
156 { 156 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
157 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); 157 try
158 try 158 {
159 { 159 QueueItemStruct BlankQIS = new QueueItemStruct();
160 QueueItemStruct BlankQIS = new QueueItemStruct(); 160 while (true)
161 while (true) 161 {
162 { 162 try
163 try 163 {
164 { 164 QueueItemStruct QIS = BlankQIS;
165 QueueItemStruct QIS = BlankQIS; 165 bool GotItem = false;
166 bool GotItem = false; 166
167 167 if (eventQueue.Count == 0)
168 if (eventQueue.Count == 0) 168 {
169 { 169 // Nothing to do? Sleep a bit waiting for something to do
170 // Nothing to do? Sleep a bit waiting for something to do 170 Thread.Sleep(nothingToDoSleepms);
171 Thread.Sleep(nothingToDoSleepms); 171 }
172 } 172 else
173 else 173 {
174 { 174 // Something in queue, process
175 // Something in queue, process 175 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
176 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); 176
177 177 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
178 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD 178 lock (queueLock)
179 lock (queueLock) 179 {
180 { 180 GotItem = false;
181 GotItem = false; 181 for (int qc = 0; qc < eventQueue.Count; qc++)
182 for (int qc = 0; qc < eventQueue.Count; qc++) 182 {
183 { 183 // Get queue item
184 // Get queue item 184 QIS = eventQueue.Dequeue();
185 QIS = eventQueue.Dequeue(); 185
186 186 // Check if object is being processed by someone else
187 // Check if object is being processed by someone else 187 if (TryLock(QIS.localID) == false)
188 if (TryLock(QIS.localID) == false) 188 {
189 { 189 // Object is already being processed, requeue it
190 // Object is already being processed, requeue it 190 eventQueue.Enqueue(QIS);
191 eventQueue.Enqueue(QIS); 191 }
192 } 192 else
193 else 193 {
194 { 194 // We have lock on an object and can process it
195 // We have lock on an object and can process it 195 GotItem = true;
196 GotItem = true; 196 break;
197 break; 197 }
198 } 198 } // go through queue
199 } // go through queue 199 } // lock
200 } // lock 200
201 201 if (GotItem == true)
202 if (GotItem == true) 202 {
203 { 203 // Execute function
204 // Execute function 204 try
205 try 205 {
206 { 206#if DEBUG
207#if DEBUG 207 m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n"
208 m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n" 208 + "QIS.localID: " + QIS.localID
209 + "QIS.localID: " + QIS.localID 209 + ", QIS.itemID: " + QIS.itemID
210 + ", QIS.itemID: " + QIS.itemID 210 + ", QIS.functionName: " + QIS.functionName);
211 + ", QIS.functionName: " + QIS.functionName); 211#endif
212#endif 212 m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID,
213 m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, 213 QIS.functionName, QIS.param);
214 QIS.functionName, QIS.param); 214 }
215 } 215 catch (Exception e)
216 catch (Exception e) 216 {
217 { 217 // DISPLAY ERROR INWORLD
218 // DISPLAY ERROR INWORLD 218 string text = "Error executing script function \"" + QIS.functionName + "\":\r\n";
219 string text = "Error executing script function \"" + QIS.functionName + "\":\r\n"; 219 //if (e.InnerException != null)
220 //if (e.InnerException != null) 220 //{
221 //{ 221 // Send inner exception
222 // Send inner exception 222 text += e.InnerException.Message.ToString();
223 text += e.InnerException.Message.ToString(); 223 //}
224 //} 224 //else
225 //else 225 //{
226 //{ 226 text += "\r\n";
227 text += "\r\n"; 227 // Send normal
228 // Send normal 228 text += e.Message.ToString();
229 text += e.Message.ToString(); 229 //}
230 //} 230 try
231 try 231 {
232 { 232 if (text.Length > 1500)
233 if (text.Length > 1500) 233 text = text.Substring(0, 1500);
234 text = text.Substring(0, 1500); 234 IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
235 IScriptHost m_host = m_ScriptEngine.World.GetSceneObjectPart(QIS.localID); 235 //if (m_host != null)
236 //if (m_host != null) 236 //{
237 //{ 237 m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0,
238 m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0, 238 m_host.AbsolutePosition, m_host.Name, m_host.UUID);
239 m_host.AbsolutePosition, m_host.Name, m_host.UUID); 239 }
240 } 240 catch
241 catch 241 {
242 { 242 //}
243 //} 243 //else
244 //else 244 //{
245 //{ 245 // T oconsole
246 // T oconsole 246 m_ScriptEngine.Log.Error("ScriptEngine",
247 m_ScriptEngine.Log.Error("ScriptEngine", 247 "Unable to send text in-world:\r\n" + text);
248 "Unable to send text in-world:\r\n" + text); 248 }
249 } 249 }
250 } 250 finally
251 finally 251 {
252 { 252 ReleaseLock(QIS.localID);
253 ReleaseLock(QIS.localID); 253 }
254 } 254 }
255 } 255 } // Something in queue
256 } // Something in queue 256 }
257 } 257 catch (ThreadAbortException tae)
258 catch (ThreadAbortException tae) 258 {
259 { 259 throw tae;
260 throw tae; 260 }
261 } 261 catch (Exception e)
262 catch (Exception e) 262 {
263 { 263 m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString());
264 m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString()); 264 }
265 } 265 } // while
266 } // while 266 } // try
267 } // try 267 catch (ThreadAbortException)
268 catch (ThreadAbortException) 268 {
269 { 269 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
270 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); 270 }
271 } 271 }
272 } 272
273 273 /// <summary>
274 /// <summary> 274 /// Try to get a mutex lock on localID
275 /// Try to get a mutex lock on localID 275 /// </summary>
276 /// </summary> 276 /// <param name="localID"></param>
277 /// <param name="localID"></param> 277 /// <returns></returns>
278 /// <returns></returns> 278 private bool TryLock(uint localID)
279 private bool TryLock(uint localID) 279 {
280 { 280 lock (tryLockLock)
281 lock (tryLockLock) 281 {
282 { 282 if (objectLocks.Contains(localID) == true)
283 if (objectLocks.Contains(localID) == true) 283 {
284 { 284 return false;
285 return false; 285 }
286 } 286 else
287 else 287 {
288 { 288 objectLocks.Add(localID);
289 objectLocks.Add(localID); 289 return true;
290 return true; 290 }
291 } 291 }
292 } 292 }
293 } 293
294 294 /// <summary>
295 /// <summary> 295 /// Release mutex lock on localID
296 /// Release mutex lock on localID 296 /// </summary>
297 /// </summary> 297 /// <param name="localID"></param>
298 /// <param name="localID"></param> 298 private void ReleaseLock(uint localID)
299 private void ReleaseLock(uint localID) 299 {
300 { 300 lock (tryLockLock)
301 lock (tryLockLock) 301 {
302 { 302 if (objectLocks.Contains(localID) == true)
303 if (objectLocks.Contains(localID) == true) 303 {
304 { 304 objectLocks.Remove(localID);
305 objectLocks.Remove(localID); 305 }
306 } 306 }
307 } 307 }
308 } 308
309 309
310 310 /// <summary>
311 /// <summary> 311 /// Add event to event execution queue
312 /// Add event to event execution queue 312 /// </summary>
313 /// </summary> 313 /// <param name="localID"></param>
314 /// <param name="localID"></param> 314 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
315 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param> 315 /// <param name="param">Array of parameters to match event mask</param>
316 /// <param name="param">Array of parameters to match event mask</param> 316 public void AddToObjectQueue(uint localID, string FunctionName, params object[] param)
317 public void AddToObjectQueue(uint localID, string FunctionName, params object[] param) 317 {
318 { 318 // Determine all scripts in Object and add to their queue
319 // Determine all scripts in Object and add to their queue 319 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName);
320 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding localID: " + localID + ", FunctionName: " + FunctionName); 320
321 321
322 322 // Do we have any scripts in this object at all? If not, return
323 // Do we have any scripts in this object at all? If not, return 323 if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false)
324 if (m_ScriptEngine.m_ScriptManager.Scripts.ContainsKey(localID) == false) 324 {
325 { 325 //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID.");
326 //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); 326 return;
327 return; 327 }
328 } 328
329 329 Dictionary<LLUUID, IScript>.KeyCollection scriptKeys =
330 Dictionary<LLUUID, LSL_BaseClass>.KeyCollection scriptKeys = 330 m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID);
331 m_ScriptEngine.m_ScriptManager.GetScriptKeys(localID); 331
332 332 foreach (LLUUID itemID in scriptKeys)
333 foreach (LLUUID itemID in scriptKeys) 333 {
334 { 334 // Add to each script in that object
335 // Add to each script in that object 335 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
336 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? 336 AddToScriptQueue(localID, itemID, FunctionName, param);
337 AddToScriptQueue(localID, itemID, FunctionName, param); 337 }
338 } 338 }
339 } 339
340 340 /// <summary>
341 /// <summary> 341 /// Add event to event execution queue
342 /// Add event to event execution queue 342 /// </summary>
343 /// </summary> 343 /// <param name="localID"></param>
344 /// <param name="localID"></param> 344 /// <param name="itemID"></param>
345 /// <param name="itemID"></param> 345 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param>
346 /// <param name="FunctionName">Name of the function, will be state + "_event_" + FunctionName</param> 346 /// <param name="param">Array of parameters to match event mask</param>
347 /// <param name="param">Array of parameters to match event mask</param> 347 public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param)
348 public void AddToScriptQueue(uint localID, LLUUID itemID, string FunctionName, params object[] param) 348 {
349 { 349 lock (queueLock)
350 lock (queueLock) 350 {
351 { 351 // Create a structure and add data
352 // Create a structure and add data 352 QueueItemStruct QIS = new QueueItemStruct();
353 QueueItemStruct QIS = new QueueItemStruct(); 353 QIS.localID = localID;
354 QIS.localID = localID; 354 QIS.itemID = itemID;
355 QIS.itemID = itemID; 355 QIS.functionName = FunctionName;
356 QIS.functionName = FunctionName; 356 QIS.param = param;
357 QIS.param = param; 357
358 358 // Add it to queue
359 // Add it to queue 359 eventQueue.Enqueue(QIS);
360 eventQueue.Enqueue(QIS); 360 }
361 } 361 }
362 } 362 }
363 }
364} \ No newline at end of file 363} \ No newline at end of file