aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorTedd Hansen2007-08-19 11:09:54 +0000
committerTedd Hansen2007-08-19 11:09:54 +0000
commit7770c65a7e888739dfb0c8a9ccf2dc521e99a33a (patch)
treee5542e0b0427b16a70d5dc98194330cd042fd1c4 /OpenSim/Region/ScriptEngine
parentAdded event method invoke cache to Executor. "Bind once, Invoke multiple time... (diff)
downloadopensim-SC-7770c65a7e888739dfb0c8a9ccf2dc521e99a33a.zip
opensim-SC-7770c65a7e888739dfb0c8a9ccf2dc521e99a33a.tar.gz
opensim-SC-7770c65a7e888739dfb0c8a9ccf2dc521e99a33a.tar.bz2
opensim-SC-7770c65a7e888739dfb0c8a9ccf2dc521e99a33a.tar.xz
Sped up EventQueueManager response time (scripts now respond quickly). Added support for multiple threads executing events on objects, but only one thread on one script at the time (to utilize MultiCore/hyperthreading CPU's).
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-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}