aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs201
1 files changed, 201 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
new file mode 100644
index 0000000..ad79fbc
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
@@ -0,0 +1,201 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5using libsecondlife;
6using OpenSim.Framework;
7using OpenSim.Region.Environment.Scenes.Scripting;
8
9namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
10{
11 /// <summary>
12 /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
13 /// </summary>
14 public class EventQueueThreadClass
15 {
16 /// <summary>
17 /// How many ms to sleep if queue is empty
18 /// </summary>
19 private int nothingToDoSleepms = 50;
20
21 public DateTime LastExecutionStarted;
22 public bool InExecution = false;
23
24 private EventQueueManager eventQueueManager;
25 public Thread EventQueueThread;
26 private static int ThreadCount = 0;
27
28 public EventQueueThreadClass(EventQueueManager eqm)
29 {
30 eventQueueManager = eqm;
31 Start();
32 }
33
34 ~EventQueueThreadClass()
35 {
36 Shutdown();
37 }
38
39 /// <summary>
40 /// Start thread
41 /// </summary>
42 private void Start()
43 {
44 EventQueueThread = new Thread(EventQueueThreadLoop);
45 EventQueueThread.IsBackground = true;
46 EventQueueThread.Priority = ThreadPriority.BelowNormal;
47 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
48 EventQueueThread.Start();
49
50 // Look at this... Don't you wish everyone did that solid coding everywhere? :P
51 if (ThreadCount == int.MaxValue)
52 ThreadCount = 0;
53 ThreadCount++;
54 }
55
56 public void Shutdown()
57 {
58 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
59 {
60 try
61 {
62 EventQueueThread.Abort();
63 EventQueueThread.Join();
64 }
65 catch (Exception)
66 {
67 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
68 }
69 }
70 }
71
72
73 /// <summary>
74 /// Queue processing thread loop
75 /// </summary>
76 private void EventQueueThreadLoop()
77 {
78 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
79 try
80 {
81 EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
82 while (true)
83 {
84 try
85 {
86 EventQueueManager.QueueItemStruct QIS = BlankQIS;
87 bool GotItem = false;
88
89 if (eventQueueManager.eventQueue.Count == 0)
90 {
91 // Nothing to do? Sleep a bit waiting for something to do
92 Thread.Sleep(nothingToDoSleepms);
93 }
94 else
95 {
96 // Something in queue, process
97 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
98
99 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
100 lock (eventQueueManager.queueLock)
101 {
102 GotItem = false;
103 for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++)
104 {
105 // Get queue item
106 QIS = eventQueueManager.eventQueue.Dequeue();
107
108 // Check if object is being processed by someone else
109 if (eventQueueManager.TryLock(QIS.localID) == false)
110 {
111 // Object is already being processed, requeue it
112 eventQueueManager.eventQueue.Enqueue(QIS);
113 }
114 else
115 {
116 // We have lock on an object and can process it
117 GotItem = true;
118 break;
119 }
120 } // go through queue
121 } // lock
122
123 if (GotItem == true)
124 {
125 // Execute function
126 try
127 {
128#if DEBUG
129 eventQueueManager.m_ScriptEngine.Log.Debug("ScriptEngine", "Executing event:\r\n"
130 + "QIS.localID: " + QIS.localID
131 + ", QIS.itemID: " + QIS.itemID
132 + ", QIS.functionName: " + QIS.functionName);
133#endif
134 LastExecutionStarted = DateTime.Now;
135 InExecution = true;
136 eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID,
137 QIS.functionName, QIS.llDetectParams, QIS.param);
138 InExecution = false;
139 }
140 catch (Exception e)
141 {
142 InExecution = false;
143 // DISPLAY ERROR INWORLD
144 string text = "Error executing script function \"" + QIS.functionName + "\":\r\n";
145 if (e.InnerException != null)
146 {
147 // Send inner exception
148 text += e.InnerException.Message.ToString();
149 }
150 else
151 {
152 text += "\r\n";
153 // Send normal
154 text += e.Message.ToString();
155 }
156 try
157 {
158 if (text.Length > 1500)
159 text = text.Substring(0, 1500);
160 IScriptHost m_host = eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
161 //if (m_host != null)
162 //{
163 eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text), ChatTypeEnum.Say, 0,
164 m_host.AbsolutePosition, m_host.Name, m_host.UUID);
165 }
166 catch
167 {
168 //}
169 //else
170 //{
171 // T oconsole
172 eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine",
173 "Unable to send text in-world:\r\n" + text);
174 }
175 }
176 finally
177 {
178 InExecution = false;
179 eventQueueManager.ReleaseLock(QIS.localID);
180 }
181 }
182 } // Something in queue
183 }
184 catch (ThreadAbortException tae)
185 {
186 throw tae;
187 }
188 catch (Exception e)
189 {
190 eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString());
191 }
192 } // while
193 } // try
194 catch (ThreadAbortException)
195 {
196 //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
197 }
198 }
199
200 }
201}