aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs156
1 files changed, 117 insertions, 39 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
index 311d32b..ec34bb0 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs
@@ -42,8 +42,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
42 [Serializable] 42 [Serializable]
43 class EventQueueManager 43 class EventQueueManager
44 { 44 {
45 private Thread EventQueueThread; 45 private List<Thread> EventQueueThreads = new List<Thread>();
46 private int NothingToDoSleepms = 200; 46 private object QueueLock = new object();
47 private int NothingToDoSleepms = 50;
48 private int NumberOfThreads = 2;
47 private Queue<QueueItemStruct> EventQueue = new Queue<QueueItemStruct>(); 49 private Queue<QueueItemStruct> EventQueue = new Queue<QueueItemStruct>();
48 private struct QueueItemStruct 50 private struct QueueItemStruct
49 { 51 {
@@ -59,26 +61,36 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
59 myScriptEngine = _ScriptEngine; 61 myScriptEngine = _ScriptEngine;
60 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Start"); 62 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Start");
61 // Start worker thread 63 // Start worker thread
62 EventQueueThread = new Thread(EventQueueThreadLoop); 64
63 EventQueueThread.IsBackground = true; 65 for (int ThreadCount = 0; ThreadCount <= NumberOfThreads; ThreadCount++)
64 EventQueueThread.Name = "EventQueueManagerThread"; 66 {
65 EventQueueThread.Start(); 67 Thread EventQueueThread = new Thread(EventQueueThreadLoop);
68 EventQueueThreads.Add(EventQueueThread);
69 EventQueueThread.IsBackground = true;
70 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
71 EventQueueThread.Start();
72 }
66 } 73 }
67 ~EventQueueManager() 74 ~EventQueueManager()
68 { 75 {
69 // Kill worker thread 76
70 if (EventQueueThread != null && EventQueueThread.IsAlive == true) 77 // Kill worker threads
78 foreach (Thread EventQueueThread in new System.Collections.ArrayList(EventQueueThreads))
71 { 79 {
72 try 80 if (EventQueueThread != null && EventQueueThread.IsAlive == true)
73 {
74 EventQueueThread.Abort();
75 EventQueueThread.Join();
76 }
77 catch (Exception e)
78 { 81 {
79 myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString()); 82 try
83 {
84 EventQueueThread.Abort();
85 EventQueueThread.Join();
86 }
87 catch (Exception e)
88 {
89 myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Exception killing worker thread: " + e.ToString());
90 }
80 } 91 }
81 } 92 }
93 EventQueueThreads.Clear();
82 // Todo: Clean up our queues 94 // Todo: Clean up our queues
83 95
84 } 96 }
@@ -88,8 +100,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
88 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned"); 100 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Worker thread spawned");
89 try 101 try
90 { 102 {
103 QueueItemStruct BlankQIS = new QueueItemStruct();
91 while (true) 104 while (true)
92 { 105 {
106 QueueItemStruct QIS = BlankQIS;
107 bool GotItem = false;
108
93 if (EventQueue.Count == 0) 109 if (EventQueue.Count == 0)
94 { 110 {
95 // Nothing to do? Sleep a bit waiting for something to do 111 // Nothing to do? Sleep a bit waiting for something to do
@@ -98,45 +114,107 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
98 else 114 else
99 { 115 {
100 // Something in queue, process 116 // Something in queue, process
101 QueueItemStruct QIS = EventQueue.Dequeue();
102 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for ObjectID: " + QIS.ObjectID + ", ScriptID: " + QIS.ScriptID + ", FunctionName: " + QIS.FunctionName); 117 //myScriptEngine.m_logger.Verbose("ScriptEngine", "Processing event for ObjectID: " + QIS.ObjectID + ", ScriptID: " + QIS.ScriptID + ", FunctionName: " + QIS.FunctionName);
103 // TODO: Execute function 118
104 myScriptEngine.myScriptManager.ExecuteEvent(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param); 119 // OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
105 } 120 lock (QueueLock)
106 } 121 {
107 } 122 GotItem = false;
123 for (int qc = 0; qc < EventQueue.Count; qc++)
124 {
125 // Get queue item
126 QIS = EventQueue.Dequeue();
127
128 // Check if object is being processed by someone else
129 if (TryLock(QIS.ObjectID) == false)
130 {
131 // Object is already being processed, requeue it
132 EventQueue.Enqueue(QIS);
133 }
134 else
135 {
136 // We have lock on an object and can process it
137 GotItem = true;
138 break;
139 }
140 } // go through queue
141 } // lock
142
143 if (GotItem == true)
144 {
145 // Execute function
146 myScriptEngine.myScriptManager.ExecuteEvent(QIS.ObjectID, QIS.ScriptID, QIS.FunctionName, QIS.param);
147 ReleaseLock(QIS.ObjectID);
148 }
149
150 } // Something in queue
151 } // while
152 } // try
108 catch (ThreadAbortException tae) 153 catch (ThreadAbortException tae)
109 { 154 {
110 myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message); 155 myScriptEngine.Log.Verbose("ScriptEngine", "EventQueueManager Worker thread killed: " + tae.Message);
111 } 156 }
112 } 157 }
113 158
159 private List<IScriptHost> ObjectLocks = new List<IScriptHost>();
160 private object TryLockLock = new object();
161 private bool TryLock(IScriptHost ObjectID)
162 {
163 lock (TryLockLock)
164 {
165 if (ObjectLocks.Contains(ObjectID) == true)
166 {
167 return false;
168 }
169 else
170 {
171 ObjectLocks.Add(ObjectID);
172 return true;
173 }
174 }
175 }
176
177 private void ReleaseLock(IScriptHost ObjectID)
178 {
179 lock (TryLockLock)
180 {
181 if (ObjectLocks.Contains(ObjectID) == true)
182 {
183 ObjectLocks.Remove(ObjectID);
184 }
185 }
186 }
187
114 public void AddToObjectQueue(IScriptHost ObjectID, string FunctionName, object[] param) 188 public void AddToObjectQueue(IScriptHost ObjectID, string FunctionName, object[] param)
115 { 189 {
116 // Determine all scripts in Object and add to their queue 190 // Determine all scripts in Object and add to their queue
117 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding ObjectID: " + ObjectID + ", FunctionName: " + FunctionName); 191 //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventQueueManager Adding ObjectID: " + ObjectID + ", FunctionName: " + FunctionName);
118 192
119 foreach (string ScriptID in myScriptEngine.myScriptManager.GetScriptKeys(ObjectID)) 193 lock (QueueLock)
120 { 194 {
121 // Add to each script in that object 195
122 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter? 196 foreach (string ScriptID in myScriptEngine.myScriptManager.GetScriptKeys(ObjectID))
123 197 {
124 // Create a structure and add data 198 // Add to each script in that object
125 QueueItemStruct QIS = new QueueItemStruct(); 199 // TODO: Some scripts may not subscribe to this event. Should we NOT add it? Does it matter?
126 QIS.ObjectID = ObjectID; 200
127 QIS.ScriptID = ScriptID; 201 // Create a structure and add data
128 QIS.FunctionName = FunctionName; 202 QueueItemStruct QIS = new QueueItemStruct();
129 QIS.param = param; 203 QIS.ObjectID = ObjectID;
130 204 QIS.ScriptID = ScriptID;
131 // Add it to queue 205 QIS.FunctionName = FunctionName;
132 EventQueue.Enqueue(QIS); 206 QIS.param = param;
133 207
208 // Add it to queue
209 EventQueue.Enqueue(QIS);
210
211 }
134 } 212 }
213 //public void AddToScriptQueue(string ObjectID, string FunctionName, object[] param)
214 //{
215 // // Add to script queue
216 //}
135 } 217 }
136 //public void AddToScriptQueue(string ObjectID, string FunctionName, object[] param)
137 //{
138 // // Add to script queue
139 //}
140 218
141 } 219 }
142} 220}