diff options
Diffstat (limited to 'OpenSim/Framework/Util.cs')
-rw-r--r-- | OpenSim/Framework/Util.cs | 93 |
1 files changed, 83 insertions, 10 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 38729c6..d09bd6d 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -41,19 +41,36 @@ using System.Security.Cryptography; | |||
41 | using System.Text; | 41 | using System.Text; |
42 | using System.Text.RegularExpressions; | 42 | using System.Text.RegularExpressions; |
43 | using System.Xml; | 43 | using System.Xml; |
44 | using System.Threading; | ||
44 | using log4net; | 45 | using log4net; |
45 | using Nini.Config; | 46 | using Nini.Config; |
46 | using Nwc.XmlRpc; | 47 | using Nwc.XmlRpc; |
48 | using BclExtras; | ||
47 | using OpenMetaverse; | 49 | using OpenMetaverse; |
48 | using OpenMetaverse.StructuredData; | 50 | using OpenMetaverse.StructuredData; |
51 | using Amib.Threading; | ||
49 | 52 | ||
50 | namespace OpenSim.Framework | 53 | namespace OpenSim.Framework |
51 | { | 54 | { |
52 | /// <summary> | 55 | /// <summary> |
56 | /// The method used by Util.FireAndForget for asynchronously firing events | ||
57 | /// </summary> | ||
58 | public enum FireAndForgetMethod | ||
59 | { | ||
60 | UnsafeQueueUserWorkItem, | ||
61 | QueueUserWorkItem, | ||
62 | BeginInvoke, | ||
63 | SmartThreadPool, | ||
64 | Thread, | ||
65 | } | ||
66 | |||
67 | /// <summary> | ||
53 | /// Miscellaneous utility functions | 68 | /// Miscellaneous utility functions |
54 | /// </summary> | 69 | /// </summary> |
55 | public class Util | 70 | public class Util |
56 | { | 71 | { |
72 | private static SmartThreadPool m_ThreadPool = null; | ||
73 | |||
57 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 74 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
58 | 75 | ||
59 | private static uint nextXferID = 5000; | 76 | private static uint nextXferID = 5000; |
@@ -69,7 +86,9 @@ namespace OpenSim.Framework | |||
69 | 86 | ||
70 | public static readonly Regex UUIDPattern | 87 | public static readonly Regex UUIDPattern |
71 | = new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); | 88 | = new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"); |
72 | 89 | ||
90 | public static FireAndForgetMethod FireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; | ||
91 | |||
73 | /// <summary> | 92 | /// <summary> |
74 | /// Linear interpolates B<->C using percent A | 93 | /// Linear interpolates B<->C using percent A |
75 | /// </summary> | 94 | /// </summary> |
@@ -1269,24 +1288,78 @@ namespace OpenSim.Framework | |||
1269 | 1288 | ||
1270 | #region FireAndForget Threading Pattern | 1289 | #region FireAndForget Threading Pattern |
1271 | 1290 | ||
1272 | public static void FireAndForget(System.Threading.WaitCallback callback) | 1291 | /// <summary> |
1292 | /// Created to work around a limitation in Mono with nested delegates | ||
1293 | /// </summary> | ||
1294 | private class FireAndForgetWrapper | ||
1273 | { | 1295 | { |
1274 | callback.BeginInvoke(null, EndFireAndForget, callback); | 1296 | public void FireAndForget(System.Threading.WaitCallback callback) |
1297 | { | ||
1298 | callback.BeginInvoke(null, EndFireAndForget, callback); | ||
1299 | } | ||
1300 | |||
1301 | public void FireAndForget(System.Threading.WaitCallback callback, object obj) | ||
1302 | { | ||
1303 | callback.BeginInvoke(obj, EndFireAndForget, callback); | ||
1304 | } | ||
1305 | |||
1306 | private static void EndFireAndForget(IAsyncResult ar) | ||
1307 | { | ||
1308 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; | ||
1309 | |||
1310 | try { callback.EndInvoke(ar); } | ||
1311 | catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } | ||
1312 | |||
1313 | ar.AsyncWaitHandle.Close(); | ||
1314 | } | ||
1275 | } | 1315 | } |
1276 | 1316 | ||
1277 | public static void FireAndForget(System.Threading.WaitCallback callback, object obj) | 1317 | public static void FireAndForget(System.Threading.WaitCallback callback) |
1278 | { | 1318 | { |
1279 | callback.BeginInvoke(obj, EndFireAndForget, callback); | 1319 | FireAndForget(callback, null); |
1280 | } | 1320 | } |
1281 | 1321 | ||
1282 | private static void EndFireAndForget(IAsyncResult ar) | 1322 | public static void SetMaxThreads(int maxThreads) |
1283 | { | 1323 | { |
1284 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; | 1324 | if (m_ThreadPool != null) |
1325 | return; | ||
1326 | |||
1327 | STPStartInfo startInfo = new STPStartInfo(); | ||
1328 | startInfo.IdleTimeout = 2000; // 2 seconds | ||
1329 | startInfo.MaxWorkerThreads = maxThreads; | ||
1330 | startInfo.MinWorkerThreads = 2; | ||
1331 | startInfo.StackSize = 524288; | ||
1332 | startInfo.ThreadPriority = ThreadPriority.Normal; | ||
1285 | 1333 | ||
1286 | try { callback.EndInvoke(ar); } | 1334 | startInfo.StartSuspended = false; |
1287 | catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } | 1335 | |
1336 | m_ThreadPool = new SmartThreadPool(startInfo); | ||
1337 | } | ||
1288 | 1338 | ||
1289 | ar.AsyncWaitHandle.Close(); | 1339 | public static void FireAndForget(System.Threading.WaitCallback callback, object obj) |
1340 | { | ||
1341 | switch (FireAndForgetMethod) | ||
1342 | { | ||
1343 | case FireAndForgetMethod.UnsafeQueueUserWorkItem: | ||
1344 | System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj); | ||
1345 | break; | ||
1346 | case FireAndForgetMethod.QueueUserWorkItem: | ||
1347 | System.Threading.ThreadPool.QueueUserWorkItem(callback, obj); | ||
1348 | break; | ||
1349 | case FireAndForgetMethod.BeginInvoke: | ||
1350 | FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); | ||
1351 | wrapper.FireAndForget(callback, obj); | ||
1352 | break; | ||
1353 | case FireAndForgetMethod.SmartThreadPool: | ||
1354 | m_ThreadPool.QueueWorkItem(delegate(object o) { callback(o); return null; }, obj); | ||
1355 | break; | ||
1356 | case FireAndForgetMethod.Thread: | ||
1357 | System.Threading.Thread thread = new System.Threading.Thread(delegate(object o) { callback(o); }); | ||
1358 | thread.Start(obj); | ||
1359 | break; | ||
1360 | default: | ||
1361 | throw new NotImplementedException(); | ||
1362 | } | ||
1290 | } | 1363 | } |
1291 | 1364 | ||
1292 | #endregion FireAndForget Threading Pattern | 1365 | #endregion FireAndForget Threading Pattern |