diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs | 156 |
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 | } |