From 8a336c6860d66b9fbba6922c32e7a57fd355c57e Mon Sep 17 00:00:00 2001
From: Melanie
Date: Thu, 22 Oct 2009 02:28:53 +0100
Subject: Add MaxPoolThreads in startup to limit the size of the thread pool
 used for FireAndForget. This lets us limit concurrency to make OpenSim play
 nice

---
 OpenSim/Framework/Util.cs             | 34 ++++++++++++++++----------
 OpenSim/Region/Application/OpenSim.cs |  2 ++
 bin/OpenSim.ini.example               |  3 +++
 prebuild.xml                          | 45 ++++++++++++++++++-----------------
 4 files changed, 50 insertions(+), 34 deletions(-)

diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index d5ae3b7..9dfb75e 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -41,12 +41,14 @@ using System.Security.Cryptography;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Xml;
+using System.Threading;
 using log4net;
 using Nini.Config;
 using Nwc.XmlRpc;
 using BclExtras;
 using OpenMetaverse;
 using OpenMetaverse.StructuredData;
+using Amib.Threading;
 
 namespace OpenSim.Framework
 {
@@ -55,6 +57,8 @@ namespace OpenSim.Framework
     /// </summary>
     public class Util
     {
+        private static SmartThreadPool m_ThreadPool = null;
+
         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
         private static uint nextXferID = 5000;
@@ -1293,22 +1297,28 @@ namespace OpenSim.Framework
             System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null);
         }
 
-        public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
+        public static void SetMaxThreads(int maxThreads)
         {
-            //FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
-            //wrapper.FireAndForget(callback, obj);
-            System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
-        }
+            STPStartInfo startInfo = new STPStartInfo();
+            startInfo.IdleTimeout = 2000; // 2 seconds
+            startInfo.MaxWorkerThreads = maxThreads;
+            startInfo.MinWorkerThreads = 5;
+            startInfo.StackSize = 524288;
+            startInfo.ThreadPriority = ThreadPriority.Normal;
 
-        /*private static void EndFireAndForget(IAsyncResult ar)
-        {
-            System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
+            startInfo.StartSuspended = false;
 
-            try { callback.EndInvoke(ar); }
-            catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
+            m_ThreadPool = new SmartThreadPool(startInfo);
+        }
 
-            ar.AsyncWaitHandle.Close();
-        }*/
+        public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
+        {
+            m_ThreadPool.QueueWorkItem(new WorkItemCallback(delegate(object o)
+                {
+                    callback(o);
+                    return null;
+                }), obj);
+        }
 
         #endregion FireAndForget Threading Pattern
     }
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 143dd2a..42e2a1e 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -67,6 +67,8 @@ namespace OpenSim
 
             IConfig startupConfig = m_config.Source.Configs["Startup"];
 
+            Util.SetMaxThreads(startupConfig.GetInt("MaxPoolThreads", 30));
+
             if (startupConfig != null)
             {
                 m_startupCommandsFile = startupConfig.GetString("startup_console_commands_file", "startup_commands.txt");
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 2d56f4e..92e6d91 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -42,6 +42,9 @@
     ; Set this to the DLL containing the client stack to use.
     clientstack_plugin="OpenSim.Region.ClientStack.LindenUDP.dll"
 
+    ; Max threads to allocate on the FireAndForget pool
+    MaxPoolThreads = 30
+
     ; ##
     ; ## REGIONS
     ; ##
diff --git a/prebuild.xml b/prebuild.xml
index e17da9a..81f907d 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -117,6 +117,28 @@
       </Files>
     </Project>
 
+    <Project frameworkVersion="v3_5" name="SmartThreadPool" path="ThirdParty/SmartThreadPool" type="Library">
+      <Configuration name="Debug">
+        <Options>
+          <OutputPath>../../bin/</OutputPath>
+        </Options>
+      </Configuration>
+      <Configuration name="Release">
+        <Options>
+          <OutputPath>../../bin/</OutputPath>
+        </Options>
+      </Configuration>
+
+      <ReferencePath>../../bin/</ReferencePath>
+      <Reference name="System"/>
+      <Reference name="System.Xml"/>
+      <Reference name="System.Data"/>
+      <Reference name="System.Web"/>
+      <Files>
+        <Match pattern="*.cs" recurse="false"/>
+      </Files>
+    </Project>
+
     <Project frameworkVersion="v3_5" name="OpenSim.Framework" path="OpenSim/Framework" type="Library">
       <Configuration name="Debug">
         <Options>
@@ -145,6 +167,7 @@
       <Reference name="Nini.dll" />
       <Reference name="log4net.dll"/>
       <Reference name="Mono.Addins.dll" />
+      <Reference name="SmartThreadPool" />
       <Files>
         <Match pattern="*.cs" recurse="false"/>
         <Match path="Client" pattern="*.cs" recurse="true"/>
@@ -2387,28 +2410,6 @@
       </Files>
     </Project>
 
-    <Project frameworkVersion="v3_5" name="SmartThreadPool" path="ThirdParty/SmartThreadPool" type="Library">
-      <Configuration name="Debug">
-        <Options>
-          <OutputPath>../../bin/</OutputPath>
-        </Options>
-      </Configuration>
-      <Configuration name="Release">
-        <Options>
-          <OutputPath>../../bin/</OutputPath>
-        </Options>
-      </Configuration>
-
-      <ReferencePath>../../bin/</ReferencePath>
-      <Reference name="System"/>
-      <Reference name="System.Xml"/>
-      <Reference name="System.Data"/>
-      <Reference name="System.Web"/>
-      <Files>
-        <Match pattern="*.cs" recurse="false"/>
-      </Files>
-    </Project>
-
     <Project frameworkVersion="v3_5" name="OpenSim.Region.ScriptEngine.Shared" path="OpenSim/Region/ScriptEngine/Shared" type="Library">
       <Configuration name="Debug">
         <Options>
-- 
cgit v1.1