diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs | 82 |
1 files changed, 59 insertions, 23 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs index e610c36..c19d641 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs | |||
@@ -12,12 +12,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
12 | /// <summary> | 12 | /// <summary> |
13 | /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class | 13 | /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class |
14 | /// </summary> | 14 | /// </summary> |
15 | public class EventQueueThreadClass | 15 | public class EventQueueThreadClass: iScriptEngineFunctionModule |
16 | { | 16 | { |
17 | /// <summary> | 17 | /// <summary> |
18 | /// How many ms to sleep if queue is empty | 18 | /// How many ms to sleep if queue is empty |
19 | /// </summary> | 19 | /// </summary> |
20 | private int nothingToDoSleepms;// = 50; | 20 | private int nothingToDoSleepms;// = 50; |
21 | private ThreadPriority MyThreadPriority; | ||
21 | 22 | ||
22 | public long LastExecutionStarted; | 23 | public long LastExecutionStarted; |
23 | public bool InExecution = false; | 24 | public bool InExecution = false; |
@@ -26,25 +27,27 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
26 | private EventQueueManager eventQueueManager; | 27 | private EventQueueManager eventQueueManager; |
27 | public Thread EventQueueThread; | 28 | public Thread EventQueueThread; |
28 | private static int ThreadCount = 0; | 29 | private static int ThreadCount = 0; |
29 | private ThreadPriority MyThreadPriority; | 30 | |
31 | private string ScriptEngineName = "ScriptEngine.Common"; | ||
30 | 32 | ||
31 | public EventQueueThreadClass(EventQueueManager eqm) | 33 | public EventQueueThreadClass(EventQueueManager eqm) |
32 | { | 34 | { |
33 | eventQueueManager = eqm; | 35 | eventQueueManager = eqm; |
34 | nothingToDoSleepms = eqm.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); | 36 | ReadConfig(); |
35 | Start(); | 37 | Start(); |
36 | } | 38 | } |
37 | 39 | ||
38 | ~EventQueueThreadClass() | 40 | ~EventQueueThreadClass() |
39 | { | 41 | { |
40 | Shutdown(); | 42 | Stop(); |
41 | } | 43 | } |
42 | 44 | ||
43 | /// <summary> | 45 | |
44 | /// Start thread | 46 | public void ReadConfig() |
45 | /// </summary> | ||
46 | private void Start() | ||
47 | { | 47 | { |
48 | ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName; | ||
49 | nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50); | ||
50 | |||
48 | // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually | 51 | // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually |
49 | string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); | 52 | string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); |
50 | switch (pri.ToLower()) | 53 | switch (pri.ToLower()) |
@@ -70,6 +73,19 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
70 | break; | 73 | break; |
71 | } | 74 | } |
72 | 75 | ||
76 | // Now set that priority | ||
77 | if (EventQueueThread != null) | ||
78 | if (EventQueueThread.IsAlive) | ||
79 | EventQueueThread.Priority = MyThreadPriority; | ||
80 | |||
81 | } | ||
82 | |||
83 | |||
84 | /// <summary> | ||
85 | /// Start thread | ||
86 | /// </summary> | ||
87 | private void Start() | ||
88 | { | ||
73 | 89 | ||
74 | EventQueueThread = new Thread(EventQueueThreadLoop); | 90 | EventQueueThread = new Thread(EventQueueThreadLoop); |
75 | EventQueueThread.IsBackground = true; | 91 | EventQueueThread.IsBackground = true; |
@@ -84,18 +100,20 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
84 | ThreadCount++; | 100 | ThreadCount++; |
85 | } | 101 | } |
86 | 102 | ||
87 | public void Shutdown() | 103 | public void Stop() |
88 | { | 104 | { |
105 | PleaseShutdown = true; // Set shutdown flag | ||
106 | Thread.Sleep(100); // Wait a bit | ||
89 | if (EventQueueThread != null && EventQueueThread.IsAlive == true) | 107 | if (EventQueueThread != null && EventQueueThread.IsAlive == true) |
90 | { | 108 | { |
91 | try | 109 | try |
92 | { | 110 | { |
93 | EventQueueThread.Abort(); | 111 | EventQueueThread.Abort(); // Send abort |
94 | EventQueueThread.Join(); | 112 | EventQueueThread.Join(); // Wait for it |
95 | } | 113 | } |
96 | catch (Exception) | 114 | catch (Exception) |
97 | { | 115 | { |
98 | //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); | 116 | //myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Exception killing worker thread: " + e.ToString()); |
99 | } | 117 | } |
100 | } | 118 | } |
101 | } | 119 | } |
@@ -106,10 +124,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
106 | /// </summary> | 124 | /// </summary> |
107 | private void EventQueueThreadLoop() | 125 | private void EventQueueThreadLoop() |
108 | { | 126 | { |
109 | //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); | 127 | //myScriptEngine.m_logger.Verbose(ScriptEngineName, "EventQueueManager Worker thread spawned"); |
110 | try | 128 | try |
111 | { | 129 | { |
112 | while (true) | 130 | while (true) |
113 | { | 131 | { |
114 | try | 132 | try |
115 | { | 133 | { |
@@ -117,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
117 | while (true) | 135 | while (true) |
118 | { | 136 | { |
119 | // Every now and then check if we should shut down | 137 | // Every now and then check if we should shut down |
120 | if (eventQueueManager.ThreadsToExit > 0) | 138 | if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0) |
121 | { | 139 | { |
122 | // Someone should shut down, lets get exclusive lock | 140 | // Someone should shut down, lets get exclusive lock |
123 | lock (eventQueueManager.ThreadsToExitLock) | 141 | lock (eventQueueManager.ThreadsToExitLock) |
@@ -125,9 +143,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
125 | // Lets re-check in case someone grabbed it | 143 | // Lets re-check in case someone grabbed it |
126 | if (eventQueueManager.ThreadsToExit > 0) | 144 | if (eventQueueManager.ThreadsToExit > 0) |
127 | { | 145 | { |
128 | // We are go for shutdown | 146 | // Its crowded here so we'll shut down |
129 | eventQueueManager.ThreadsToExit--; | 147 | eventQueueManager.ThreadsToExit--; |
130 | Shutdown(); | 148 | Stop(); |
149 | return; | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | // We have been asked to shut down | ||
154 | Stop(); | ||
131 | return; | 155 | return; |
132 | } | 156 | } |
133 | } | 157 | } |
@@ -139,6 +163,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
139 | EventQueueManager.QueueItemStruct QIS = BlankQIS; | 163 | EventQueueManager.QueueItemStruct QIS = BlankQIS; |
140 | bool GotItem = false; | 164 | bool GotItem = false; |
141 | 165 | ||
166 | if (PleaseShutdown) | ||
167 | return; | ||
168 | |||
142 | if (eventQueueManager.eventQueue.Count == 0) | 169 | if (eventQueueManager.eventQueue.Count == 0) |
143 | { | 170 | { |
144 | // Nothing to do? Sleep a bit waiting for something to do | 171 | // Nothing to do? Sleep a bit waiting for something to do |
@@ -147,7 +174,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
147 | else | 174 | else |
148 | { | 175 | { |
149 | // Something in queue, process | 176 | // Something in queue, process |
150 | //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); | 177 | //myScriptEngine.m_logger.Verbose(ScriptEngineName, "Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName); |
151 | 178 | ||
152 | // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD | 179 | // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD |
153 | lock (eventQueueManager.queueLock) | 180 | lock (eventQueueManager.queueLock) |
@@ -179,7 +206,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
179 | try | 206 | try |
180 | { | 207 | { |
181 | #if DEBUG | 208 | #if DEBUG |
182 | eventQueueManager.m_ScriptEngine.Log.Debug("ScriptEngine", | 209 | eventQueueManager.m_ScriptEngine.Log.Debug(ScriptEngineName, |
183 | "Executing event:\r\n" | 210 | "Executing event:\r\n" |
184 | + "QIS.localID: " + QIS.localID | 211 | + "QIS.localID: " + QIS.localID |
185 | + ", QIS.itemID: " + QIS.itemID | 212 | + ", QIS.itemID: " + QIS.itemID |
@@ -235,7 +262,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
235 | //else | 262 | //else |
236 | //{ | 263 | //{ |
237 | // T oconsole | 264 | // T oconsole |
238 | eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", | 265 | eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName, |
239 | "Unable to send text in-world:\r\n" + | 266 | "Unable to send text in-world:\r\n" + |
240 | text); | 267 | text); |
241 | } | 268 | } |
@@ -260,19 +287,28 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
260 | } | 287 | } |
261 | catch (ThreadAbortException tae) | 288 | catch (ThreadAbortException tae) |
262 | { | 289 | { |
263 | eventQueueManager.m_ScriptEngine.Log.Notice("ScriptEngine", "ThreadAbortException while executing function."); | 290 | eventQueueManager.m_ScriptEngine.Log.Notice(ScriptEngineName, "ThreadAbortException while executing function."); |
264 | } | 291 | } |
265 | catch (Exception e) | 292 | catch (Exception e) |
266 | { | 293 | { |
267 | eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", "Exception in EventQueueThreadLoop: " + e.ToString()); | 294 | eventQueueManager.m_ScriptEngine.Log.Error(ScriptEngineName, "Exception in EventQueueThreadLoop: " + e.ToString()); |
268 | } | 295 | } |
269 | } // while | 296 | } // while |
270 | } // try | 297 | } // try |
271 | catch (ThreadAbortException) | 298 | catch (ThreadAbortException) |
272 | { | 299 | { |
273 | //myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); | 300 | //myScriptEngine.Log.Verbose(ScriptEngineName, "EventQueueManager Worker thread killed: " + tae.Message); |
274 | } | 301 | } |
275 | } | 302 | } |
276 | 303 | ||
304 | /// <summary> | ||
305 | /// If set to true then threads and stuff should try to make a graceful exit | ||
306 | /// </summary> | ||
307 | public bool PleaseShutdown | ||
308 | { | ||
309 | get { return _PleaseShutdown; } | ||
310 | set { _PleaseShutdown = value; } | ||
311 | } | ||
312 | private bool _PleaseShutdown = false; | ||
277 | } | 313 | } |
278 | } | 314 | } |