Update SmartThreadPool to latest version 2.2.3 with a major and minor change.

SmartThreadPool code comes from http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
This version implements thread abort (via WorkItem.Cancel(true)), threadpool naming, max thread stack, etc. so we no longer need to manually patch those.
However, two changes have been made to stock 2.2.3.
Major change: WorkItem.Cancel(bool abortExecution) in our version does not succeed if the work item was in progress and thread abort was not specified.
This is to match previous behaviour where we handle co-operative termination via another mechanism rather than checking WorkItem.IsCanceled.
Minor change: Did not add STP's StopWatch implementation as this is only used WinCE and Silverlight and causes a build clash with System.Diagnostics.StopWatch
The reason for updating is to see if this improves http://opensimulator.org/mantis/view.php?id=6557 and http://opensimulator.org/mantis/view.php?id=6586
This commit is contained in:
Justin Clark-Casey (justincc)
2013-05-01 19:01:43 +01:00
parent ac135c649c
commit 206fb306a7
31 changed files with 6690 additions and 4804 deletions

View File

@@ -1,223 +1,138 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Web;
using System.Runtime.Remoting.Messaging;
namespace Amib.Threading
{
#region CallerThreadContext class
/// <summary>
/// This class stores the caller call context in order to restore
/// it when the work item is executed in the thread pool environment.
/// </summary>
internal class CallerThreadContext
{
#region Prepare reflection information
// Cached type information.
private static MethodInfo getLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static MethodInfo setLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static string HttpContextSlotName = GetHttpContextSlotName();
private static string GetHttpContextSlotName()
{
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
if( fi != null )
return (string)fi.GetValue(null);
else // Use the default "HttpContext" slot name
return "HttpContext";
}
#endregion
#region Private fields
private HttpContext _httpContext = null;
private LogicalCallContext _callContext = null;
#endregion
/// <summary>
/// Constructor
/// </summary>
private CallerThreadContext()
{
}
public bool CapturedCallContext
{
get
{
return (null != _callContext);
}
}
public bool CapturedHttpContext
{
get
{
return (null != _httpContext);
}
}
/// <summary>
/// Captures the current thread context
/// </summary>
/// <returns></returns>
public static CallerThreadContext Capture(
bool captureCallContext,
bool captureHttpContext)
{
Debug.Assert(captureCallContext || captureHttpContext);
CallerThreadContext callerThreadContext = new CallerThreadContext();
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
// Capture Call Context
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
{
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
if (callerThreadContext._callContext != null)
{
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
}
}
// Capture httpContext
if (captureHttpContext && (null != HttpContext.Current))
{
callerThreadContext._httpContext = HttpContext.Current;
}
return callerThreadContext;
}
/// <summary>
/// Applies the thread context stored earlier
/// </summary>
/// <param name="callerThreadContext"></param>
public static void Apply(CallerThreadContext callerThreadContext)
{
if (null == callerThreadContext)
{
throw new ArgumentNullException("callerThreadContext");
}
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
// Restore call context
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
{
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
}
// Restore HttpContext
if (callerThreadContext._httpContext != null)
{
CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
}
}
}
#endregion
}
/*
// Ami Bar
// amibar@gmail.com
using System;
using System.Threading;
using System.Globalization;
using System.Security.Principal;
using System.Reflection;
using System.Runtime.Remoting.Contexts;
namespace Amib.Threading.Internal
{
#region CallerThreadContext class
/// <summary>
/// This class stores the caller thread context in order to restore
/// it when the work item is executed in the context of the thread
/// from the pool.
/// Note that we can't store the thread's CompressedStack, because
/// it throws a security exception
/// </summary>
public class CallerThreadContext
{
private CultureInfo _culture = null;
private CultureInfo _cultureUI = null;
private IPrincipal _principal;
private System.Runtime.Remoting.Contexts.Context _context;
private static FieldInfo _fieldInfo = GetFieldInfo();
private static FieldInfo GetFieldInfo()
{
Type threadType = typeof(Thread);
return threadType.GetField(
"m_Context",
BindingFlags.Instance | BindingFlags.NonPublic);
}
/// <summary>
/// Constructor
/// </summary>
private CallerThreadContext()
{
}
/// <summary>
/// Captures the current thread context
/// </summary>
/// <returns></returns>
public static CallerThreadContext Capture()
{
CallerThreadContext callerThreadContext = new CallerThreadContext();
Thread thread = Thread.CurrentThread;
callerThreadContext._culture = thread.CurrentCulture;
callerThreadContext._cultureUI = thread.CurrentUICulture;
callerThreadContext._principal = Thread.CurrentPrincipal;
callerThreadContext._context = Thread.CurrentContext;
return callerThreadContext;
}
/// <summary>
/// Applies the thread context stored earlier
/// </summary>
/// <param name="callerThreadContext"></param>
public static void Apply(CallerThreadContext callerThreadContext)
{
Thread thread = Thread.CurrentThread;
thread.CurrentCulture = callerThreadContext._culture;
thread.CurrentUICulture = callerThreadContext._cultureUI;
Thread.CurrentPrincipal = callerThreadContext._principal;
// Uncomment the following block to enable the Thread.CurrentThread
/*
if (null != _fieldInfo)
{
_fieldInfo.SetValue(
Thread.CurrentThread,
callerThreadContext._context);
}
* /
}
}
#endregion
}
*/
#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
using System;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Web;
using System.Runtime.Remoting.Messaging;
namespace Amib.Threading.Internal
{
#region CallerThreadContext class
/// <summary>
/// This class stores the caller call context in order to restore
/// it when the work item is executed in the thread pool environment.
/// </summary>
internal class CallerThreadContext
{
#region Prepare reflection information
// Cached type information.
private static readonly MethodInfo getLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly MethodInfo setLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static string HttpContextSlotName = GetHttpContextSlotName();
private static string GetHttpContextSlotName()
{
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
if (fi != null)
{
return (string) fi.GetValue(null);
}
return "HttpContext";
}
#endregion
#region Private fields
private HttpContext _httpContext;
private LogicalCallContext _callContext;
#endregion
/// <summary>
/// Constructor
/// </summary>
private CallerThreadContext()
{
}
public bool CapturedCallContext
{
get
{
return (null != _callContext);
}
}
public bool CapturedHttpContext
{
get
{
return (null != _httpContext);
}
}
/// <summary>
/// Captures the current thread context
/// </summary>
/// <returns></returns>
public static CallerThreadContext Capture(
bool captureCallContext,
bool captureHttpContext)
{
Debug.Assert(captureCallContext || captureHttpContext);
CallerThreadContext callerThreadContext = new CallerThreadContext();
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
// Capture Call Context
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
{
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
if (callerThreadContext._callContext != null)
{
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
}
}
// Capture httpContext
if (captureHttpContext && (null != HttpContext.Current))
{
callerThreadContext._httpContext = HttpContext.Current;
}
return callerThreadContext;
}
/// <summary>
/// Applies the thread context stored earlier
/// </summary>
/// <param name="callerThreadContext"></param>
public static void Apply(CallerThreadContext callerThreadContext)
{
if (null == callerThreadContext)
{
throw new ArgumentNullException("callerThreadContext");
}
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
// Restore call context
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
{
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
}
// Restore HttpContext
if (callerThreadContext._httpContext != null)
{
HttpContext.Current = callerThreadContext._httpContext;
//CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
}
}
}
#endregion
}
#endif