diff options
author | Melanie | 2009-10-27 11:32:11 +0000 |
---|---|---|
committer | Melanie | 2009-10-27 11:32:11 +0000 |
commit | 31a848e97bd984ab0a85feca397ce419f6ae839a (patch) | |
tree | 4743f5eb7c12b3723ed4b986d19714d1b3a0a3ea /OpenSim/Framework | |
parent | Commented out instrumentation in ODEPrim.cs (diff) | |
parent | Finally hunted down the Parallel deadlock. Packets were being handled asynchr... (diff) | |
download | opensim-SC-31a848e97bd984ab0a85feca397ce419f6ae839a.zip opensim-SC-31a848e97bd984ab0a85feca397ce419f6ae839a.tar.gz opensim-SC-31a848e97bd984ab0a85feca397ce419f6ae839a.tar.bz2 opensim-SC-31a848e97bd984ab0a85feca397ce419f6ae839a.tar.xz |
Merge branch 'master' into vehicles
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/ClientManager.cs | 5 | ||||
-rw-r--r-- | OpenSim/Framework/IScene.cs | 1 | ||||
-rw-r--r--[-rwxr-xr-x] | OpenSim/Framework/MinHeap.cs | 27 | ||||
-rw-r--r-- | OpenSim/Framework/Parallel.cs | 3 | ||||
-rw-r--r-- | OpenSim/Framework/PluginLoader.cs | 9 | ||||
-rw-r--r-- | OpenSim/Framework/PrimitiveBaseShape.cs | 66 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 8 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs | 6 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/VersionInfo.cs | 4 | ||||
-rw-r--r-- | OpenSim/Framework/Util.cs | 42 | ||||
-rw-r--r-- | OpenSim/Framework/Watchdog.cs | 183 |
11 files changed, 276 insertions, 78 deletions
diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index 61b59e7..baff2f4 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs | |||
@@ -204,7 +204,10 @@ namespace OpenSim.Framework | |||
204 | public void ForEach(Action<IClientAPI> action) | 204 | public void ForEach(Action<IClientAPI> action) |
205 | { | 205 | { |
206 | IClientAPI[] localArray = m_array; | 206 | IClientAPI[] localArray = m_array; |
207 | Parallel.ForEach<IClientAPI>(localArray, action); | 207 | Parallel.For(0, localArray.Length, |
208 | delegate(int i) | ||
209 | { action(localArray[i]); } | ||
210 | ); | ||
208 | } | 211 | } |
209 | 212 | ||
210 | /// <summary> | 213 | /// <summary> |
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index f34027d..8067052 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs | |||
@@ -62,7 +62,6 @@ namespace OpenSim.Framework | |||
62 | RegionInfo RegionInfo { get; } | 62 | RegionInfo RegionInfo { get; } |
63 | RegionStatus RegionStatus { get; set; } | 63 | RegionStatus RegionStatus { get; set; } |
64 | 64 | ||
65 | ClientManager ClientManager { get; } | ||
66 | IConfigSource Config { get; } | 65 | IConfigSource Config { get; } |
67 | 66 | ||
68 | float TimeDilation { get; } | 67 | float TimeDilation { get; } |
diff --git a/OpenSim/Framework/MinHeap.cs b/OpenSim/Framework/MinHeap.cs index ad39bbc..33d0364 100755..100644 --- a/OpenSim/Framework/MinHeap.cs +++ b/OpenSim/Framework/MinHeap.cs | |||
@@ -1,3 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
1 | using System; | 28 | using System; |
2 | using System.Threading; | 29 | using System.Threading; |
3 | using System.Collections; | 30 | using System.Collections; |
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs index 70eecdc..515852f 100644 --- a/OpenSim/Framework/Parallel.cs +++ b/OpenSim/Framework/Parallel.cs | |||
@@ -118,6 +118,7 @@ namespace OpenSim.Framework | |||
118 | int counter = threadCount; | 118 | int counter = threadCount; |
119 | AutoResetEvent threadFinishEvent = new AutoResetEvent(false); | 119 | AutoResetEvent threadFinishEvent = new AutoResetEvent(false); |
120 | IEnumerator<T> enumerator = enumerable.GetEnumerator(); | 120 | IEnumerator<T> enumerator = enumerable.GetEnumerator(); |
121 | object syncRoot = new object(); | ||
121 | Exception exception = null; | 122 | Exception exception = null; |
122 | 123 | ||
123 | for (int i = 0; i < threadCount; i++) | 124 | for (int i = 0; i < threadCount; i++) |
@@ -131,7 +132,7 @@ namespace OpenSim.Framework | |||
131 | { | 132 | { |
132 | T entry; | 133 | T entry; |
133 | 134 | ||
134 | lock (enumerator) | 135 | lock (syncRoot) |
135 | { | 136 | { |
136 | if (!enumerator.MoveNext()) | 137 | if (!enumerator.MoveNext()) |
137 | break; | 138 | break; |
diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs index 5d38f5f..819cb7b 100644 --- a/OpenSim/Framework/PluginLoader.cs +++ b/OpenSim/Framework/PluginLoader.cs | |||
@@ -194,10 +194,15 @@ namespace OpenSim.Framework | |||
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | /// <summary> | ||
198 | /// Unregisters Mono.Addins event handlers, allowing temporary Mono.Addins | ||
199 | /// data to be garbage collected. Since the plugins created by this loader | ||
200 | /// are meant to outlive the loader itself, they must be disposed separately | ||
201 | /// </summary> | ||
197 | public void Dispose() | 202 | public void Dispose() |
198 | { | 203 | { |
199 | foreach (T plugin in Plugins) | 204 | AddinManager.AddinLoadError -= on_addinloaderror_; |
200 | plugin.Dispose(); | 205 | AddinManager.AddinLoaded -= on_addinloaded_; |
201 | } | 206 | } |
202 | 207 | ||
203 | private void initialise_plugin_dir_(string dir) | 208 | private void initialise_plugin_dir_(string dir) |
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index b646f92..5e4d175 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs | |||
@@ -76,7 +76,7 @@ namespace OpenSim.Framework | |||
76 | { | 76 | { |
77 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 77 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
78 | 78 | ||
79 | private static readonly Primitive.TextureEntry m_defaultTexture; | 79 | private static readonly byte[] DEFAULT_TEXTURE = new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")).GetBytes(); |
80 | 80 | ||
81 | private byte[] m_textureEntry; | 81 | private byte[] m_textureEntry; |
82 | 82 | ||
@@ -104,33 +104,32 @@ namespace OpenSim.Framework | |||
104 | private HollowShape _hollowShape; | 104 | private HollowShape _hollowShape; |
105 | 105 | ||
106 | // Sculpted | 106 | // Sculpted |
107 | [XmlIgnore] private UUID _sculptTexture = UUID.Zero; | 107 | [XmlIgnore] private UUID _sculptTexture; |
108 | [XmlIgnore] private byte _sculptType = (byte)0; | 108 | [XmlIgnore] private byte _sculptType; |
109 | [XmlIgnore] private byte[] _sculptData = new byte[0]; | 109 | [XmlIgnore] private byte[] _sculptData = Utils.EmptyBytes; |
110 | [XmlIgnore] private Image _sculptBitmap = null; | ||
111 | 110 | ||
112 | // Flexi | 111 | // Flexi |
113 | [XmlIgnore] private int _flexiSoftness = 0; | 112 | [XmlIgnore] private int _flexiSoftness; |
114 | [XmlIgnore] private float _flexiTension = 0f; | 113 | [XmlIgnore] private float _flexiTension; |
115 | [XmlIgnore] private float _flexiDrag = 0f; | 114 | [XmlIgnore] private float _flexiDrag; |
116 | [XmlIgnore] private float _flexiGravity = 0f; | 115 | [XmlIgnore] private float _flexiGravity; |
117 | [XmlIgnore] private float _flexiWind = 0f; | 116 | [XmlIgnore] private float _flexiWind; |
118 | [XmlIgnore] private float _flexiForceX = 0f; | 117 | [XmlIgnore] private float _flexiForceX; |
119 | [XmlIgnore] private float _flexiForceY = 0f; | 118 | [XmlIgnore] private float _flexiForceY; |
120 | [XmlIgnore] private float _flexiForceZ = 0f; | 119 | [XmlIgnore] private float _flexiForceZ; |
121 | 120 | ||
122 | //Bright n sparkly | 121 | //Bright n sparkly |
123 | [XmlIgnore] private float _lightColorR = 0f; | 122 | [XmlIgnore] private float _lightColorR; |
124 | [XmlIgnore] private float _lightColorG = 0f; | 123 | [XmlIgnore] private float _lightColorG; |
125 | [XmlIgnore] private float _lightColorB = 0f; | 124 | [XmlIgnore] private float _lightColorB; |
126 | [XmlIgnore] private float _lightColorA = 1f; | 125 | [XmlIgnore] private float _lightColorA = 1.0f; |
127 | [XmlIgnore] private float _lightRadius = 0f; | 126 | [XmlIgnore] private float _lightRadius; |
128 | [XmlIgnore] private float _lightCutoff = 0f; | 127 | [XmlIgnore] private float _lightCutoff; |
129 | [XmlIgnore] private float _lightFalloff = 0f; | 128 | [XmlIgnore] private float _lightFalloff; |
130 | [XmlIgnore] private float _lightIntensity = 1f; | 129 | [XmlIgnore] private float _lightIntensity = 1.0f; |
131 | [XmlIgnore] private bool _flexiEntry = false; | 130 | [XmlIgnore] private bool _flexiEntry; |
132 | [XmlIgnore] private bool _lightEntry = false; | 131 | [XmlIgnore] private bool _lightEntry; |
133 | [XmlIgnore] private bool _sculptEntry = false; | 132 | [XmlIgnore] private bool _sculptEntry; |
134 | 133 | ||
135 | public byte ProfileCurve | 134 | public byte ProfileCurve |
136 | { | 135 | { |
@@ -172,17 +171,11 @@ namespace OpenSim.Framework | |||
172 | } | 171 | } |
173 | } | 172 | } |
174 | 173 | ||
175 | static PrimitiveBaseShape() | ||
176 | { | ||
177 | m_defaultTexture = | ||
178 | new Primitive.TextureEntry(new UUID("89556747-24cb-43ed-920b-47caed15465f")); | ||
179 | } | ||
180 | |||
181 | public PrimitiveBaseShape() | 174 | public PrimitiveBaseShape() |
182 | { | 175 | { |
183 | PCode = (byte) PCodeEnum.Primitive; | 176 | PCode = (byte) PCodeEnum.Primitive; |
184 | ExtraParams = new byte[1]; | 177 | ExtraParams = new byte[1]; |
185 | Textures = m_defaultTexture; | 178 | m_textureEntry = DEFAULT_TEXTURE; |
186 | } | 179 | } |
187 | 180 | ||
188 | public PrimitiveBaseShape(bool noShape) | 181 | public PrimitiveBaseShape(bool noShape) |
@@ -192,7 +185,7 @@ namespace OpenSim.Framework | |||
192 | 185 | ||
193 | PCode = (byte)PCodeEnum.Primitive; | 186 | PCode = (byte)PCodeEnum.Primitive; |
194 | ExtraParams = new byte[1]; | 187 | ExtraParams = new byte[1]; |
195 | Textures = m_defaultTexture; | 188 | m_textureEntry = DEFAULT_TEXTURE; |
196 | } | 189 | } |
197 | 190 | ||
198 | [XmlIgnore] | 191 | [XmlIgnore] |
@@ -577,15 +570,6 @@ namespace OpenSim.Framework | |||
577 | } | 570 | } |
578 | } | 571 | } |
579 | 572 | ||
580 | public Image SculptBitmap { | ||
581 | get { | ||
582 | return _sculptBitmap; | ||
583 | } | ||
584 | set { | ||
585 | _sculptBitmap = value; | ||
586 | } | ||
587 | } | ||
588 | |||
589 | public int FlexiSoftness { | 573 | public int FlexiSoftness { |
590 | get { | 574 | get { |
591 | return _flexiSoftness; | 575 | return _flexiSoftness; |
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 85d7be2..bec5ed3 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -1559,15 +1559,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
1559 | public void Start() | 1559 | public void Start() |
1560 | { | 1560 | { |
1561 | m_log.Info("[HTTPD]: Starting up HTTP Server"); | 1561 | m_log.Info("[HTTPD]: Starting up HTTP Server"); |
1562 | |||
1563 | //m_workerThread = new Thread(new ThreadStart(StartHTTP)); | ||
1564 | //m_workerThread.Name = "HttpThread"; | ||
1565 | //m_workerThread.IsBackground = true; | ||
1566 | //m_workerThread.Start(); | ||
1567 | //ThreadTracker.Add(m_workerThread); | ||
1568 | StartHTTP(); | 1562 | StartHTTP(); |
1569 | |||
1570 | |||
1571 | } | 1563 | } |
1572 | 1564 | ||
1573 | private void StartHTTP() | 1565 | private void StartHTTP() |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 1c54581..e7a64f7 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs | |||
@@ -50,9 +50,7 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
50 | m_WorkerThreadCount = pWorkerThreadCount; | 50 | m_WorkerThreadCount = pWorkerThreadCount; |
51 | m_workerThreads = new Thread[m_WorkerThreadCount]; | 51 | m_workerThreads = new Thread[m_WorkerThreadCount]; |
52 | m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; | 52 | m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; |
53 | m_watcherThread = new Thread(ThreadStart); | ||
54 | 53 | ||
55 | |||
56 | //startup worker threads | 54 | //startup worker threads |
57 | for (uint i=0;i<m_WorkerThreadCount;i++) | 55 | for (uint i=0;i<m_WorkerThreadCount;i++) |
58 | { | 56 | { |
@@ -65,11 +63,11 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
65 | m_workerThreads[i].Start(); | 63 | m_workerThreads[i].Start(); |
66 | 64 | ||
67 | } | 65 | } |
66 | |||
68 | //start watcher threads | 67 | //start watcher threads |
68 | m_watcherThread = new Thread(ThreadStart); | ||
69 | m_watcherThread.Name = "PollServiceWatcherThread"; | 69 | m_watcherThread.Name = "PollServiceWatcherThread"; |
70 | m_watcherThread.Start(); | 70 | m_watcherThread.Start(); |
71 | |||
72 | |||
73 | } | 71 | } |
74 | 72 | ||
75 | internal void ReQueueEvent(PollServiceHttpRequest req) | 73 | internal void ReQueueEvent(PollServiceHttpRequest req) |
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 62e7e92..9f98310 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs | |||
@@ -29,8 +29,8 @@ namespace OpenSim | |||
29 | { | 29 | { |
30 | public class VersionInfo | 30 | public class VersionInfo |
31 | { | 31 | { |
32 | private const string VERSION_NUMBER = "0.6.7"; | 32 | private const string VERSION_NUMBER = "0.6.8"; |
33 | private const Flavour VERSION_FLAVOUR = Flavour.RC1; | 33 | private const Flavour VERSION_FLAVOUR = Flavour.Dev; |
34 | 34 | ||
35 | public enum Flavour | 35 | public enum Flavour |
36 | { | 36 | { |
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index d09bd6d..10f38ab 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -69,8 +69,6 @@ namespace OpenSim.Framework | |||
69 | /// </summary> | 69 | /// </summary> |
70 | public class Util | 70 | public class Util |
71 | { | 71 | { |
72 | private static SmartThreadPool m_ThreadPool = null; | ||
73 | |||
74 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 72 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
75 | 73 | ||
76 | private static uint nextXferID = 5000; | 74 | private static uint nextXferID = 5000; |
@@ -79,6 +77,9 @@ namespace OpenSim.Framework | |||
79 | private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]"; | 77 | private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]"; |
80 | private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]"; | 78 | private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]"; |
81 | private static object XferLock = new object(); | 79 | private static object XferLock = new object(); |
80 | /// <summary>Thread pool used for Util.FireAndForget if | ||
81 | /// FireAndForgetMethod.SmartThreadPool is used</summary> | ||
82 | private static SmartThreadPool m_ThreadPool; | ||
82 | 83 | ||
83 | // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. | 84 | // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. |
84 | private static readonly DateTime unixEpoch = | 85 | private static readonly DateTime unixEpoch = |
@@ -1319,21 +1320,14 @@ namespace OpenSim.Framework | |||
1319 | FireAndForget(callback, null); | 1320 | FireAndForget(callback, null); |
1320 | } | 1321 | } |
1321 | 1322 | ||
1322 | public static void SetMaxThreads(int maxThreads) | 1323 | public static void InitThreadPool(int maxThreads) |
1323 | { | 1324 | { |
1325 | if (maxThreads < 2) | ||
1326 | throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); | ||
1324 | if (m_ThreadPool != null) | 1327 | if (m_ThreadPool != null) |
1325 | return; | 1328 | throw new InvalidOperationException("SmartThreadPool is already initialized"); |
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; | ||
1333 | 1329 | ||
1334 | startInfo.StartSuspended = false; | 1330 | m_ThreadPool = new SmartThreadPool(2000, maxThreads, 2); |
1335 | |||
1336 | m_ThreadPool = new SmartThreadPool(startInfo); | ||
1337 | } | 1331 | } |
1338 | 1332 | ||
1339 | public static void FireAndForget(System.Threading.WaitCallback callback, object obj) | 1333 | public static void FireAndForget(System.Threading.WaitCallback callback, object obj) |
@@ -1341,20 +1335,22 @@ namespace OpenSim.Framework | |||
1341 | switch (FireAndForgetMethod) | 1335 | switch (FireAndForgetMethod) |
1342 | { | 1336 | { |
1343 | case FireAndForgetMethod.UnsafeQueueUserWorkItem: | 1337 | case FireAndForgetMethod.UnsafeQueueUserWorkItem: |
1344 | System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj); | 1338 | ThreadPool.UnsafeQueueUserWorkItem(callback, obj); |
1345 | break; | 1339 | break; |
1346 | case FireAndForgetMethod.QueueUserWorkItem: | 1340 | case FireAndForgetMethod.QueueUserWorkItem: |
1347 | System.Threading.ThreadPool.QueueUserWorkItem(callback, obj); | 1341 | ThreadPool.QueueUserWorkItem(callback, obj); |
1348 | break; | 1342 | break; |
1349 | case FireAndForgetMethod.BeginInvoke: | 1343 | case FireAndForgetMethod.BeginInvoke: |
1350 | FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); | 1344 | FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); |
1351 | wrapper.FireAndForget(callback, obj); | 1345 | wrapper.FireAndForget(callback, obj); |
1352 | break; | 1346 | break; |
1353 | case FireAndForgetMethod.SmartThreadPool: | 1347 | case FireAndForgetMethod.SmartThreadPool: |
1354 | m_ThreadPool.QueueWorkItem(delegate(object o) { callback(o); return null; }, obj); | 1348 | if (m_ThreadPool == null) |
1349 | m_ThreadPool = new SmartThreadPool(2000, 15, 2); | ||
1350 | m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { callback, obj }); | ||
1355 | break; | 1351 | break; |
1356 | case FireAndForgetMethod.Thread: | 1352 | case FireAndForgetMethod.Thread: |
1357 | System.Threading.Thread thread = new System.Threading.Thread(delegate(object o) { callback(o); }); | 1353 | Thread thread = new Thread(delegate(object o) { callback(o); }); |
1358 | thread.Start(obj); | 1354 | thread.Start(obj); |
1359 | break; | 1355 | break; |
1360 | default: | 1356 | default: |
@@ -1362,6 +1358,16 @@ namespace OpenSim.Framework | |||
1362 | } | 1358 | } |
1363 | } | 1359 | } |
1364 | 1360 | ||
1361 | private static object SmartThreadPoolCallback(object o) | ||
1362 | { | ||
1363 | object[] array = (object[])o; | ||
1364 | WaitCallback callback = (WaitCallback)array[0]; | ||
1365 | object obj = array[1]; | ||
1366 | |||
1367 | callback(obj); | ||
1368 | return null; | ||
1369 | } | ||
1370 | |||
1365 | #endregion FireAndForget Threading Pattern | 1371 | #endregion FireAndForget Threading Pattern |
1366 | } | 1372 | } |
1367 | } | 1373 | } |
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs new file mode 100644 index 0000000..5d46905 --- /dev/null +++ b/OpenSim/Framework/Watchdog.cs | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Threading; | ||
31 | using log4net; | ||
32 | |||
33 | namespace OpenSim.Framework | ||
34 | { | ||
35 | /// <summary> | ||
36 | /// Manages launching threads and keeping watch over them for timeouts | ||
37 | /// </summary> | ||
38 | public static class Watchdog | ||
39 | { | ||
40 | /// <summary>Timer interval in milliseconds for the watchdog timer</summary> | ||
41 | const double WATCHDOG_INTERVAL_MS = 2500.0d; | ||
42 | /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary> | ||
43 | const int WATCHDOG_TIMEOUT_MS = 5000; | ||
44 | |||
45 | [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] | ||
46 | private class ThreadWatchdogInfo | ||
47 | { | ||
48 | public Thread Thread; | ||
49 | public int LastTick; | ||
50 | |||
51 | public ThreadWatchdogInfo(Thread thread) | ||
52 | { | ||
53 | Thread = thread; | ||
54 | LastTick = Environment.TickCount & Int32.MaxValue; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | /// <summary> | ||
59 | /// This event is called whenever a tracked thread is stopped or | ||
60 | /// has not called UpdateThread() in time | ||
61 | /// </summary> | ||
62 | /// <param name="thread">The thread that has been identified as dead</param> | ||
63 | /// <param name="lastTick">The last time this thread called UpdateThread()</param> | ||
64 | public delegate void WatchdogTimeout(Thread thread, int lastTick); | ||
65 | |||
66 | /// <summary>This event is called whenever a tracked thread is | ||
67 | /// stopped or has not called UpdateThread() in time</summary> | ||
68 | public static event WatchdogTimeout OnWatchdogTimeout; | ||
69 | |||
70 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
71 | private static Dictionary<int, ThreadWatchdogInfo> m_threads; | ||
72 | private static System.Timers.Timer m_watchdogTimer; | ||
73 | |||
74 | static Watchdog() | ||
75 | { | ||
76 | m_threads = new Dictionary<int, ThreadWatchdogInfo>(); | ||
77 | m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); | ||
78 | m_watchdogTimer.AutoReset = false; | ||
79 | m_watchdogTimer.Elapsed += WatchdogTimerElapsed; | ||
80 | m_watchdogTimer.Start(); | ||
81 | } | ||
82 | |||
83 | /// <summary> | ||
84 | /// Start a new thread that is tracked by the watchdog timer | ||
85 | /// </summary> | ||
86 | /// <param name="start">The method that will be executed in a new thread</param> | ||
87 | /// <param name="name">A name to give to the new thread</param> | ||
88 | /// <param name="priority">Priority to run the thread at</param> | ||
89 | /// <param name="isBackground">True to run this thread as a background | ||
90 | /// thread, otherwise false</param> | ||
91 | /// <returns>The newly created Thread object</returns> | ||
92 | public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground) | ||
93 | { | ||
94 | Thread thread = new Thread(start); | ||
95 | thread.Name = name; | ||
96 | thread.Priority = priority; | ||
97 | thread.IsBackground = isBackground; | ||
98 | thread.Start(); | ||
99 | |||
100 | return thread; | ||
101 | } | ||
102 | |||
103 | /// <summary> | ||
104 | /// Marks the current thread as alive | ||
105 | /// </summary> | ||
106 | public static void UpdateThread() | ||
107 | { | ||
108 | UpdateThread(Thread.CurrentThread.ManagedThreadId); | ||
109 | } | ||
110 | |||
111 | /// <summary> | ||
112 | /// Stops watchdog tracking on the current thread | ||
113 | /// </summary> | ||
114 | /// <returns>True if the thread was removed from the list of tracked | ||
115 | /// threads, otherwise false</returns> | ||
116 | public static bool RemoveThread() | ||
117 | { | ||
118 | return RemoveThread(Thread.CurrentThread.ManagedThreadId); | ||
119 | } | ||
120 | |||
121 | private static void AddThread(ThreadWatchdogInfo threadInfo) | ||
122 | { | ||
123 | m_log.Debug("[WATCHDOG]: Started tracking thread \"" + threadInfo.Thread.Name + "\" (ID " + threadInfo.Thread.ManagedThreadId + ")"); | ||
124 | |||
125 | lock (m_threads) | ||
126 | m_threads.Add(threadInfo.Thread.ManagedThreadId, threadInfo); | ||
127 | } | ||
128 | |||
129 | private static bool RemoveThread(int threadID) | ||
130 | { | ||
131 | lock (m_threads) | ||
132 | return m_threads.Remove(threadID); | ||
133 | } | ||
134 | |||
135 | private static void UpdateThread(int threadID) | ||
136 | { | ||
137 | ThreadWatchdogInfo threadInfo; | ||
138 | |||
139 | // Although TryGetValue is not a thread safe operation, we use a try/catch here instead | ||
140 | // of a lock for speed. Adding/removing threads is a very rare operation compared to | ||
141 | // UpdateThread(), and a single UpdateThread() failure here and there won't break | ||
142 | // anything | ||
143 | try | ||
144 | { | ||
145 | if (m_threads.TryGetValue(threadID, out threadInfo)) | ||
146 | threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; | ||
147 | else | ||
148 | AddThread(new ThreadWatchdogInfo(Thread.CurrentThread)); | ||
149 | } | ||
150 | catch { } | ||
151 | } | ||
152 | |||
153 | private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) | ||
154 | { | ||
155 | WatchdogTimeout callback = OnWatchdogTimeout; | ||
156 | |||
157 | if (callback != null) | ||
158 | { | ||
159 | ThreadWatchdogInfo timedOut = null; | ||
160 | |||
161 | lock (m_threads) | ||
162 | { | ||
163 | int now = Environment.TickCount & Int32.MaxValue; | ||
164 | |||
165 | foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) | ||
166 | { | ||
167 | if (threadInfo.Thread.ThreadState == ThreadState.Stopped || now - threadInfo.LastTick >= WATCHDOG_TIMEOUT_MS) | ||
168 | { | ||
169 | timedOut = threadInfo; | ||
170 | m_threads.Remove(threadInfo.Thread.ManagedThreadId); | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | if (timedOut != null) | ||
177 | callback(timedOut.Thread, timedOut.LastTick); | ||
178 | } | ||
179 | |||
180 | m_watchdogTimer.Start(); | ||
181 | } | ||
182 | } | ||
183 | } | ||