Merge branch 'master' into careminster

Conflicts:
	ThirdParty/SmartThreadPool/SmartThreadPool.cs
avinationmerge
Melanie 2013-05-01 21:39:49 +01:00
commit 8c5445b774
37 changed files with 6745 additions and 4828 deletions

View File

@ -158,7 +158,7 @@ namespace OpenSim.Framework.Capabilities
/// capabilities and their handler details. /// capabilities and their handler details.
/// </summary> /// </summary>
/// <param name="excludeSeed">If true, then exclude the seed cap.</param> /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
public Hashtable GetCapsDetails(bool excludeSeed) public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
{ {
Hashtable caps = new Hashtable(); Hashtable caps = new Hashtable();
string protocol = "http://"; string protocol = "http://";
@ -175,6 +175,9 @@ namespace OpenSim.Framework.Capabilities
if (excludeSeed && "SEED" == capsName) if (excludeSeed && "SEED" == capsName)
continue; continue;
if (requestedCaps != null && !requestedCaps.Contains(capsName))
continue;
caps[capsName] = baseUrl + m_capsHandlers[capsName].Path; caps[capsName] = baseUrl + m_capsHandlers[capsName].Path;
} }
} }
@ -182,4 +185,4 @@ namespace OpenSim.Framework.Capabilities
return caps; return caps;
} }
} }
} }

View File

@ -1852,7 +1852,7 @@ namespace OpenSim.Framework
case FireAndForgetMethod.SmartThreadPool: case FireAndForgetMethod.SmartThreadPool:
if (m_ThreadPool == null) if (m_ThreadPool == null)
InitThreadPool(15); InitThreadPool(15);
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
break; break;
case FireAndForgetMethod.Thread: case FireAndForgetMethod.Thread:
Thread thread = new Thread(delegate(object o) { realCallback(o); }); Thread thread = new Thread(delegate(object o) { realCallback(o); });
@ -1922,15 +1922,15 @@ namespace OpenSim.Framework
return sb.ToString(); return sb.ToString();
} }
private static object SmartThreadPoolCallback(object o) // private static object SmartThreadPoolCallback(object o)
{ // {
object[] array = (object[])o; // object[] array = (object[])o;
WaitCallback callback = (WaitCallback)array[0]; // WaitCallback callback = (WaitCallback)array[0];
object obj = array[1]; // object obj = array[1];
//
callback(obj); // callback(obj);
return null; // return null;
} // }
#endregion FireAndForget Threading Pattern #endregion FireAndForget Threading Pattern

View File

@ -355,11 +355,22 @@ namespace OpenSim.Region.ClientStack.Linden
return string.Empty; return string.Empty;
} }
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true); OSDArray capsRequested = (OSDArray)OSDParser.DeserializeLLSDXml(request);
List<string> validCaps = new List<string>();
foreach (OSD c in capsRequested)
validCaps.Add(c.AsString());
Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps);
// Add the external too // Add the external too
foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers) foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
{
if (!validCaps.Contains(kvp.Key))
continue;
caps[kvp.Key] = kvp.Value; caps[kvp.Key] = kvp.Value;
}
string result = LLSDHelpers.SerialiseLLSDReply(caps); string result = LLSDHelpers.SerialiseLLSDReply(caps);

View File

@ -252,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Framework
{ {
caps.AppendFormat("** Circuit {0}:\n", kvp.Key); caps.AppendFormat("** Circuit {0}:\n", kvp.Key);
for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
{ {
Uri uri = new Uri(kvp2.Value.ToString()); Uri uri = new Uri(kvp2.Value.ToString());
caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);

View File

@ -676,11 +676,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
} }
else else
{ {
if (remoteClient == null || so.OwnerID != remoteClient.AgentId) if (remoteClient == null || so.RootPart.OwnerID != remoteClient.AgentId)
{ {
// Taking copy of another person's item. Take to // Taking copy of another person's item. Take to
// Objects folder. // Objects folder.
folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
so.FromFolderID = UUID.Zero;
} }
else else
{ {
@ -696,7 +697,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// //
if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) if (action == DeRezAction.Take || action == DeRezAction.TakeCopy)
{ {
if (so.FromFolderID != UUID.Zero && userID == remoteClient.AgentId) if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
{ {
InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
if (f != null) if (f != null)

View File

@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
public interface IScriptWorkItem public interface IScriptWorkItem
{ {
bool Cancel(); bool Cancel();
void Abort(); bool Abort();
/// <summary> /// <summary>
/// Wait for the work item to complete. /// Wait for the work item to complete.

View File

@ -572,9 +572,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public bool Stop(int timeout) public bool Stop(int timeout)
{ {
// m_log.DebugFormat( if (DebugLevel >= 1)
// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", m_log.DebugFormat(
// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
IScriptWorkItem workItem; IScriptWorkItem workItem;

View File

@ -551,7 +551,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
/// <param name="instance"></param> /// <param name="instance"></param>
/// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
private void HandleScriptsAction<TKey>( private void HandleScriptsAction<TKey>(
string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector)
{ {
if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
return; return;
@ -1599,7 +1599,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
startInfo.MaxWorkerThreads = maxThreads; startInfo.MaxWorkerThreads = maxThreads;
startInfo.MinWorkerThreads = minThreads; startInfo.MinWorkerThreads = minThreads;
startInfo.ThreadPriority = threadPriority;; startInfo.ThreadPriority = threadPriority;;
startInfo.StackSize = stackSize; startInfo.MaxStackSize = stackSize;
startInfo.StartSuspended = true; startInfo.StartSuspended = true;
m_ThreadPool = new SmartThreadPool(startInfo); m_ThreadPool = new SmartThreadPool(startInfo);

View File

@ -52,16 +52,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return wr.Cancel(); return wr.Cancel();
} }
public void Abort() public bool Abort()
{ {
wr.Abort(); return wr.Cancel(true);
} }
public bool Wait(int t) public bool Wait(int t)
{ {
// We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
// TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
// int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8 // int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8
// (or very likely other versions of Mono at least up until 3.0.3). // (or very likely other versions of Mono at least up until 3.0.3).
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
} }

View File

@ -1,61 +0,0 @@
using System;
using System.Reflection;
using System.Runtime.InteropServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(true)]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.7.6.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

View File

@ -1,223 +1,138 @@
using System;
using System.Diagnostics; #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
using System.Threading;
using System.Reflection; using System;
using System.Web; using System.Diagnostics;
using System.Runtime.Remoting.Messaging; using System.Threading;
using System.Reflection;
using System.Web;
namespace Amib.Threading using System.Runtime.Remoting.Messaging;
{
#region CallerThreadContext class
namespace Amib.Threading.Internal
/// <summary> {
/// This class stores the caller call context in order to restore #region CallerThreadContext class
/// it when the work item is executed in the thread pool environment.
/// </summary> /// <summary>
internal class CallerThreadContext /// This class stores the caller call context in order to restore
{ /// it when the work item is executed in the thread pool environment.
#region Prepare reflection information /// </summary>
internal class CallerThreadContext
// Cached type information. {
private static MethodInfo getLogicalCallContextMethodInfo = #region Prepare reflection information
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
// Cached type information.
private static MethodInfo setLogicalCallContextMethodInfo = private static readonly MethodInfo getLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static string HttpContextSlotName = GetHttpContextSlotName(); private static readonly MethodInfo setLogicalCallContextMethodInfo =
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
private static string GetHttpContextSlotName()
{ private static string HttpContextSlotName = GetHttpContextSlotName();
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
private static string GetHttpContextSlotName()
if( fi != null ) {
return (string)fi.GetValue(null); FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
else // Use the default "HttpContext" slot name
return "HttpContext"; if (fi != null)
} {
return (string) fi.GetValue(null);
#endregion }
#region Private fields return "HttpContext";
}
private HttpContext _httpContext = null;
private LogicalCallContext _callContext = null; #endregion
#endregion #region Private fields
/// <summary> private HttpContext _httpContext;
/// Constructor private LogicalCallContext _callContext;
/// </summary>
private CallerThreadContext() #endregion
{
} /// <summary>
/// Constructor
public bool CapturedCallContext /// </summary>
{ private CallerThreadContext()
get {
{ }
return (null != _callContext);
} public bool CapturedCallContext
} {
get
public bool CapturedHttpContext {
{ return (null != _callContext);
get }
{ }
return (null != _httpContext);
} public bool CapturedHttpContext
} {
get
/// <summary> {
/// Captures the current thread context return (null != _httpContext);
/// </summary> }
/// <returns></returns> }
public static CallerThreadContext Capture(
bool captureCallContext, /// <summary>
bool captureHttpContext) /// Captures the current thread context
{ /// </summary>
Debug.Assert(captureCallContext || captureHttpContext); /// <returns></returns>
public static CallerThreadContext Capture(
CallerThreadContext callerThreadContext = new CallerThreadContext(); bool captureCallContext,
bool captureHttpContext)
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() {
// Capture Call Context Debug.Assert(captureCallContext || captureHttpContext);
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
{ CallerThreadContext callerThreadContext = new CallerThreadContext();
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
if (callerThreadContext._callContext != null) // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
{ // Capture Call Context
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); if(captureCallContext && (getLogicalCallContextMethodInfo != null))
} {
} callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
if (callerThreadContext._callContext != null)
// Capture httpContext {
if (captureHttpContext && (null != HttpContext.Current)) callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
{ }
callerThreadContext._httpContext = HttpContext.Current; }
}
// Capture httpContext
return callerThreadContext; if (captureHttpContext && (null != HttpContext.Current))
} {
callerThreadContext._httpContext = HttpContext.Current;
/// <summary> }
/// Applies the thread context stored earlier
/// </summary> return callerThreadContext;
/// <param name="callerThreadContext"></param> }
public static void Apply(CallerThreadContext callerThreadContext)
{ /// <summary>
if (null == callerThreadContext) /// Applies the thread context stored earlier
{ /// </summary>
throw new ArgumentNullException("callerThreadContext"); /// <param name="callerThreadContext"></param>
} public static void Apply(CallerThreadContext callerThreadContext)
{
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() if (null == callerThreadContext)
// Restore call context {
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) throw new ArgumentNullException("callerThreadContext");
{ }
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
} // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
// Restore call context
// Restore HttpContext if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
if (callerThreadContext._httpContext != null) {
{ setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); }
}
} // Restore HttpContext
} if (callerThreadContext._httpContext != null)
{
#endregion HttpContext.Current = callerThreadContext._httpContext;
//CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
} }
}
}
/*
// Ami Bar #endregion
// amibar@gmail.com }
#endif
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
}
*/

View File

@ -0,0 +1,14 @@
namespace Amib.Threading.Internal
{
internal class CanceledWorkItemsGroup
{
public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
public CanceledWorkItemsGroup()
{
IsCanceled = false;
}
public bool IsCanceled { get; set; }
}
}

View File

@ -0,0 +1,104 @@
#if (_WINDOWS_CE)
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Amib.Threading.Internal
{
/// <summary>
/// EventWaitHandle class
/// In WindowsCE this class doesn't exist and I needed the WaitAll and WaitAny implementation.
/// So I wrote this class to implement these two methods with some of their overloads.
/// It uses the WaitForMultipleObjects API to do the WaitAll and WaitAny.
/// Note that this class doesn't even inherit from WaitHandle!
/// </summary>
public class STPEventWaitHandle
{
#region Public Constants
public const int WaitTimeout = Timeout.Infinite;
#endregion
#region Private External Constants
private const Int32 WAIT_FAILED = -1;
private const Int32 WAIT_TIMEOUT = 0x102;
private const UInt32 INFINITE = 0xFFFFFFFF;
#endregion
#region WaitAll and WaitAny
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
{
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
}
private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles)
{
IntPtr[] nativeHandles = new IntPtr[waitHandles.Length];
for (int i = 0; i < waitHandles.Length; i++)
{
nativeHandles[i] = waitHandles[i].Handle;
}
return nativeHandles;
}
public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);
int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, true, timeout);
if (result == WAIT_TIMEOUT || result == WAIT_FAILED)
{
return false;
}
return true;
}
public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);
int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, false, timeout);
if (result >= 0 && result < waitHandles.Length)
{
return result;
}
return -1;
}
public static int WaitAny(WaitHandle[] waitHandles)
{
return WaitAny(waitHandles, Timeout.Infinite, false);
}
public static int WaitAny(WaitHandle[] waitHandles, TimeSpan timeout, bool exitContext)
{
int millisecondsTimeout = (int)timeout.TotalMilliseconds;
return WaitAny(waitHandles, millisecondsTimeout, false);
}
#endregion
#region External methods
[DllImport("coredll.dll", SetLastError = true)]
public static extern int WaitForMultipleObjects(uint nCount, IntPtr[] lpHandles, bool fWaitAll, uint dwMilliseconds);
#endregion
}
}
#endif

View File

@ -0,0 +1,82 @@
using System.Threading;
#if (_WINDOWS_CE)
using System;
using System.Runtime.InteropServices;
#endif
namespace Amib.Threading.Internal
{
/// <summary>
/// EventWaitHandleFactory class.
/// This is a static class that creates AutoResetEvent and ManualResetEvent objects.
/// In WindowCE the WaitForMultipleObjects API fails to use the Handle property
/// of XxxResetEvent. It can use only handles that were created by the CreateEvent API.
/// Consequently this class creates the needed XxxResetEvent and replaces the handle if
/// it's a WindowsCE OS.
/// </summary>
public static class EventWaitHandleFactory
{
/// <summary>
/// Create a new AutoResetEvent object
/// </summary>
/// <returns>Return a new AutoResetEvent object</returns>
public static AutoResetEvent CreateAutoResetEvent()
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
#if (_WINDOWS_CE)
ReplaceEventHandle(waitHandle, false, false);
#endif
return waitHandle;
}
/// <summary>
/// Create a new ManualResetEvent object
/// </summary>
/// <returns>Return a new ManualResetEvent object</returns>
public static ManualResetEvent CreateManualResetEvent(bool initialState)
{
ManualResetEvent waitHandle = new ManualResetEvent(initialState);
#if (_WINDOWS_CE)
ReplaceEventHandle(waitHandle, true, initialState);
#endif
return waitHandle;
}
#if (_WINDOWS_CE)
/// <summary>
/// Replace the event handle
/// </summary>
/// <param name="waitHandle">The WaitHandle object which its handle needs to be replaced.</param>
/// <param name="manualReset">Indicates if the event is a ManualResetEvent (true) or an AutoResetEvent (false)</param>
/// <param name="initialState">The initial state of the event</param>
private static void ReplaceEventHandle(WaitHandle waitHandle, bool manualReset, bool initialState)
{
// Store the old handle
IntPtr oldHandle = waitHandle.Handle;
// Create a new event
IntPtr newHandle = CreateEvent(IntPtr.Zero, manualReset, initialState, null);
// Replace the old event with the new event
waitHandle.Handle = newHandle;
// Close the old event
CloseHandle (oldHandle);
}
[DllImport("coredll.dll", SetLastError = true)]
public static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
//Handle
[DllImport("coredll.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
#endif
}
}

View File

@ -1,81 +1,111 @@
// Ami Bar using System;
// amibar@gmail.com #if !(_WINDOWS_CE)
using System.Runtime.Serialization;
using System; #endif
using System.Runtime.Serialization;
namespace Amib.Threading
namespace Amib.Threading {
{ #region Exceptions
#region Exceptions
/// <summary>
/// <summary> /// Represents an exception in case IWorkItemResult.GetResult has been canceled
/// Represents an exception in case IWorkItemResult.GetResult has been canceled /// </summary>
/// </summary> public sealed partial class WorkItemCancelException : Exception
[Serializable] {
public sealed class WorkItemCancelException : ApplicationException public WorkItemCancelException()
{ {
public WorkItemCancelException() : base() }
{
} public WorkItemCancelException(string message)
: base(message)
public WorkItemCancelException(string message) : base(message) {
{ }
}
public WorkItemCancelException(string message, Exception e)
public WorkItemCancelException(string message, Exception e) : base(message, e) : base(message, e)
{ {
} }
}
public WorkItemCancelException(SerializationInfo si, StreamingContext sc) : base(si, sc)
{ /// <summary>
} /// Represents an exception in case IWorkItemResult.GetResult has been timed out
} /// </summary>
public sealed partial class WorkItemTimeoutException : Exception
/// <summary> {
/// Represents an exception in case IWorkItemResult.GetResult has been timed out public WorkItemTimeoutException()
/// </summary> {
[Serializable] }
public sealed class WorkItemTimeoutException : ApplicationException
{ public WorkItemTimeoutException(string message)
public WorkItemTimeoutException() : base() : base(message)
{ {
} }
public WorkItemTimeoutException(string message) : base(message) public WorkItemTimeoutException(string message, Exception e)
{ : base(message, e)
} {
}
public WorkItemTimeoutException(string message, Exception e) : base(message, e) }
{
} /// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc) : base(si, sc) /// </summary>
{ public sealed partial class WorkItemResultException : Exception
} {
} public WorkItemResultException()
{
/// <summary> }
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
/// </summary> public WorkItemResultException(string message)
[Serializable] : base(message)
public sealed class WorkItemResultException : ApplicationException {
{ }
public WorkItemResultException() : base()
{ public WorkItemResultException(string message, Exception e)
} : base(message, e)
{
public WorkItemResultException(string message) : base(message) }
{ }
}
public WorkItemResultException(string message, Exception e) : base(message, e) #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
{ /// <summary>
} /// Represents an exception in case IWorkItemResult.GetResult has been canceled
/// </summary>
public WorkItemResultException(SerializationInfo si, StreamingContext sc) : base(si, sc) [Serializable]
{ public sealed partial class WorkItemCancelException
} {
} public WorkItemCancelException(SerializationInfo si, StreamingContext sc)
: base(si, sc)
#endregion {
} }
}
/// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
/// </summary>
[Serializable]
public sealed partial class WorkItemTimeoutException
{
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc)
: base(si, sc)
{
}
}
/// <summary>
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
/// </summary>
[Serializable]
public sealed partial class WorkItemResultException
{
public WorkItemResultException(SerializationInfo si, StreamingContext sc)
: base(si, sc)
{
}
}
#endif
#endregion
}

View File

@ -1,271 +1,628 @@
// Ami Bar using System;
// amibar@gmail.com using System.Threading;
using System; namespace Amib.Threading
using System.Threading; {
#region Delegates
namespace Amib.Threading
{ /// <summary>
#region Delegates /// A delegate that represents the method to run as the work item
/// </summary>
/// <summary> /// <param name="state">A state object for the method to run</param>
/// A delegate that represents the method to run as the work item public delegate object WorkItemCallback(object state);
/// </summary>
/// <param name="state">A state object for the method to run</param> /// <summary>
public delegate object WorkItemCallback(object state); /// A delegate to call after the WorkItemCallback completed
/// </summary>
/// <summary> /// <param name="wir">The work item result object</param>
/// A delegate to call after the WorkItemCallback completed public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
/// </summary>
/// <param name="wir">The work item result object</param> /// <summary>
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir); /// A delegate to call after the WorkItemCallback completed
/// </summary>
/// <summary> /// <param name="wir">The work item result object</param>
/// A delegate to call when a WorkItemsGroup becomes idle public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir);
/// </summary>
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param> /// <summary>
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup); /// A delegate to call when a WorkItemsGroup becomes idle
/// </summary>
#endregion /// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
#region WorkItem Priority
/// <summary>
public enum WorkItemPriority /// A delegate to call after a thread is created, but before
{ /// it's first use.
Lowest, /// </summary>
BelowNormal, public delegate void ThreadInitializationHandler();
Normal,
AboveNormal, /// <summary>
Highest, /// A delegate to call when a thread is about to exit, after
} /// it is no longer belong to the pool.
/// </summary>
#endregion public delegate void ThreadTerminationHandler();
#region IHasWorkItemPriority interface #endregion
public interface IHasWorkItemPriority #region WorkItem Priority
{
WorkItemPriority WorkItemPriority { get; } /// <summary>
} /// Defines the availeable priorities of a work item.
/// The higher the priority a work item has, the sooner
#endregion /// it will be executed.
/// </summary>
#region IWorkItemsGroup interface public enum WorkItemPriority
{
/// <summary> Lowest,
/// IWorkItemsGroup interface BelowNormal,
/// </summary> Normal,
public interface IWorkItemsGroup AboveNormal,
{ Highest,
/// <summary> }
/// Get/Set the name of the WorkItemsGroup
/// </summary> #endregion
string Name { get; set; }
#region IWorkItemsGroup interface
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority); /// <summary>
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state); /// IWorkItemsGroup interface
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority); /// Created by SmartThreadPool.CreateWorkItemsGroup()
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback); /// </summary>
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority); public interface IWorkItemsGroup
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute); {
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority); /// <summary>
/// Get/Set the name of the WorkItemsGroup
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback); /// </summary>
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state); string Name { get; set; }
void WaitForIdle(); /// <summary>
bool WaitForIdle(TimeSpan timeout); /// Get/Set the maximum number of workitem that execute cocurrency on the thread pool
bool WaitForIdle(int millisecondsTimeout); /// </summary>
int Concurrency { get; set; }
int WaitingCallbacks { get; }
event WorkItemsGroupIdleHandler OnIdle; /// <summary>
/// Get the number of work items waiting in the queue.
void Cancel(); /// </summary>
void Start(); int WaitingCallbacks { get; }
}
/// <summary>
#endregion /// Get an array with all the state objects of the currently running items.
/// The array represents a snap shot and impact performance.
#region CallToPostExecute enumerator /// </summary>
object[] GetStates();
[Flags]
public enum CallToPostExecute /// <summary>
{ /// Get the WorkItemsGroup start information
Never = 0x00, /// </summary>
WhenWorkItemCanceled = 0x01, WIGStartInfo WIGStartInfo { get; }
WhenWorkItemNotCanceled = 0x02,
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled, /// <summary>
} /// Starts to execute work items
/// </summary>
#endregion void Start();
#region IWorkItemResult interface /// <summary>
/// Cancel all the work items.
/// <summary> /// Same as Cancel(false)
/// IWorkItemResult interface /// </summary>
/// </summary> void Cancel();
public interface IWorkItemResult
{ /// <summary>
/// <summary> /// Cancel all work items using thread abortion
/// Get the result of the work item. /// </summary>
/// If the work item didn't run yet then the caller waits. /// <param name="abortExecution">True to stop work items by raising ThreadAbortException</param>
/// </summary> void Cancel(bool abortExecution);
/// <returns>The result of the work item</returns>
object GetResult(); /// <summary>
/// Wait for all work item to complete.
/// <summary> /// </summary>
/// Get the result of the work item. void WaitForIdle();
/// If the work item didn't run yet then the caller waits until timeout.
/// </summary> /// <summary>
/// <returns>The result of the work item</returns> /// Wait for all work item to complete, until timeout expired
/// On timeout throws WorkItemTimeoutException /// </summary>
object GetResult( /// <param name="timeout">How long to wait for the work items to complete</param>
int millisecondsTimeout, /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
bool exitContext); bool WaitForIdle(TimeSpan timeout);
/// <summary> /// <summary>
/// Get the result of the work item. /// Wait for all work item to complete, until timeout expired
/// If the work item didn't run yet then the caller waits until timeout. /// </summary>
/// </summary> /// <param name="millisecondsTimeout">How long to wait for the work items to complete in milliseconds</param>
/// <returns>The result of the work item</returns> /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
/// On timeout throws WorkItemTimeoutException bool WaitForIdle(int millisecondsTimeout);
object GetResult(
TimeSpan timeout, /// <summary>
bool exitContext); /// IsIdle is true when there are no work items running or queued.
/// </summary>
void Abort(); bool IsIdle { get; }
/// <summary> /// <summary>
/// Get the result of the work item. /// This event is fired when all work items are completed.
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. /// (When IsIdle changes to true)
/// </summary> /// This event only work on WorkItemsGroup. On SmartThreadPool
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param> /// it throws the NotImplementedException.
/// <param name="exitContext"> /// </summary>
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. event WorkItemsGroupIdleHandler OnIdle;
/// </param>
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param> #region QueueWorkItem
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException /// <summary>
/// On cancel throws WorkItemCancelException /// Queue a work item
object GetResult( /// </summary>
int millisecondsTimeout, /// <param name="callback">A callback to execute</param>
bool exitContext, /// <returns>Returns a work item result</returns>
WaitHandle cancelWaitHandle); IWorkItemResult QueueWorkItem(WorkItemCallback callback);
/// <summary> /// <summary>
/// Get the result of the work item. /// Queue a work item
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. /// </summary>
/// </summary> /// <param name="callback">A callback to execute</param>
/// <returns>The result of the work item</returns> /// <param name="workItemPriority">The priority of the work item</param>
/// On timeout throws WorkItemTimeoutException /// <returns>Returns a work item result</returns>
/// On cancel throws WorkItemCancelException IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
object GetResult(
TimeSpan timeout, /// <summary>
bool exitContext, /// Queue a work item
WaitHandle cancelWaitHandle); /// </summary>
/// <param name="callback">A callback to execute</param>
/// <summary> /// <param name="state">
/// Get the result of the work item. /// The context object of the work item. Used for passing arguments to the work item.
/// If the work item didn't run yet then the caller waits. /// </param>
/// </summary> /// <returns>Returns a work item result</returns>
/// <param name="e">Filled with the exception if one was thrown</param> IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
/// <returns>The result of the work item</returns>
object GetResult(out Exception e); /// <summary>
/// Queue a work item
/// <summary> /// </summary>
/// Get the result of the work item. /// <param name="callback">A callback to execute</param>
/// If the work item didn't run yet then the caller waits until timeout. /// <param name="state">
/// </summary> /// The context object of the work item. Used for passing arguments to the work item.
/// <param name="e">Filled with the exception if one was thrown</param> /// </param>
/// <returns>The result of the work item</returns> /// <param name="workItemPriority">The work item priority</param>
/// On timeout throws WorkItemTimeoutException /// <returns>Returns a work item result</returns>
object GetResult( IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
int millisecondsTimeout,
bool exitContext, /// <summary>
out Exception e); /// Queue a work item
/// </summary>
/// <summary> /// <param name="callback">A callback to execute</param>
/// Get the result of the work item. /// <param name="state">
/// If the work item didn't run yet then the caller waits until timeout. /// The context object of the work item. Used for passing arguments to the work item.
/// </summary> /// </param>
/// <param name="e">Filled with the exception if one was thrown</param> /// <param name="postExecuteWorkItemCallback">
/// <returns>The result of the work item</returns> /// A delegate to call after the callback completion
/// On timeout throws WorkItemTimeoutException /// </param>
object GetResult( /// <returns>Returns a work item result</returns>
TimeSpan timeout, IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
bool exitContext,
out Exception e); /// <summary>
/// Queue a work item
/// <summary> /// </summary>
/// Get the result of the work item. /// <param name="callback">A callback to execute</param>
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. /// <param name="state">
/// </summary> /// The context object of the work item. Used for passing arguments to the work item.
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param> /// </param>
/// <param name="exitContext"> /// <param name="postExecuteWorkItemCallback">
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. /// A delegate to call after the callback completion
/// </param> /// </param>
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param> /// <param name="workItemPriority">The work item priority</param>
/// <param name="e">Filled with the exception if one was thrown</param> /// <returns>Returns a work item result</returns>
/// <returns>The result of the work item</returns> IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException /// <summary>
object GetResult( /// Queue a work item
int millisecondsTimeout, /// </summary>
bool exitContext, /// <param name="callback">A callback to execute</param>
WaitHandle cancelWaitHandle, /// <param name="state">
out Exception e); /// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <summary> /// <param name="postExecuteWorkItemCallback">
/// Get the result of the work item. /// A delegate to call after the callback completion
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled. /// </param>
/// </summary> /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
/// <returns>The result of the work item</returns> /// <returns>Returns a work item result</returns>
/// <param name="e">Filled with the exception if one was thrown</param> IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException /// <summary>
object GetResult( /// Queue a work item
TimeSpan timeout, /// </summary>
bool exitContext, /// <param name="callback">A callback to execute</param>
WaitHandle cancelWaitHandle, /// <param name="state">
out Exception e); /// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <summary> /// <param name="postExecuteWorkItemCallback">
/// Gets an indication whether the asynchronous operation has completed. /// A delegate to call after the callback completion
/// </summary> /// </param>
bool IsCompleted { get; } /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
/// <param name="workItemPriority">The work item priority</param>
/// <summary> /// <returns>Returns a work item result</returns>
/// Gets an indication whether the asynchronous operation has been canceled. IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
/// </summary>
bool IsCanceled { get; } /// <summary>
/// Queue a work item
/// <summary> /// </summary>
/// Gets a user-defined object that qualifies or contains information about an asynchronous operation. /// <param name="workItemInfo">Work item info</param>
/// </summary> /// <param name="callback">A callback to execute</param>
object State { get; } /// <returns>Returns a work item result</returns>
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
/// <summary>
/// Cancel the work item if it didn't start running yet. /// <summary>
/// </summary> /// Queue a work item
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns> /// </summary>
bool Cancel(); /// <param name="workItemInfo">Work item information</param>
/// <param name="callback">A callback to execute</param>
/// <summary> /// <param name="state">
/// Get the work item's priority /// The context object of the work item. Used for passing arguments to the work item.
/// </summary> /// </param>
WorkItemPriority WorkItemPriority { get; } /// <returns>Returns a work item result</returns>
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
/// <summary>
/// Return the result, same as GetResult() #endregion
/// </summary>
object Result { get; } #region QueueWorkItem(Action<...>)
/// <summary> /// <summary>
/// Returns the exception if occured otherwise returns null. /// Queue a work item.
/// </summary> /// </summary>
object Exception { get; } /// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
} IWorkItemResult QueueWorkItem(Action action);
#endregion /// <summary>
} /// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg, WorkItemPriority priority);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2> (Action<T1, T2> action, T1 arg1, T2 arg2, WorkItemPriority priority);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2, T3> (Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult object, but its GetResult() will always return null</returns>
IWorkItemResult QueueWorkItem<T1, T2, T3, T4> (Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority);
#endregion
#region QueueWorkItem(Func<...>)
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
/// its GetResult() returns a TResult object</returns>
IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
/// its GetResult() returns a TResult object</returns>
IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
/// its GetResult() returns a TResult object</returns>
IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
/// its GetResult() returns a TResult object</returns>
IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3);
/// <summary>
/// Queue a work item.
/// </summary>
/// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
/// its GetResult() returns a TResult object</returns>
IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
#endregion
}
#endregion
#region CallToPostExecute enumerator
[Flags]
public enum CallToPostExecute
{
/// <summary>
/// Never call to the PostExecute call back
/// </summary>
Never = 0x00,
/// <summary>
/// Call to the PostExecute only when the work item is cancelled
/// </summary>
WhenWorkItemCanceled = 0x01,
/// <summary>
/// Call to the PostExecute only when the work item is not cancelled
/// </summary>
WhenWorkItemNotCanceled = 0x02,
/// <summary>
/// Always call to the PostExecute
/// </summary>
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
}
#endregion
#region IWorkItemResult interface
/// <summary>
/// The common interface of IWorkItemResult and IWorkItemResult&lt;T&gt;
/// </summary>
public interface IWaitableResult
{
/// <summary>
/// This method intent is for internal use.
/// </summary>
/// <returns></returns>
IWorkItemResult GetWorkItemResult();
/// <summary>
/// This method intent is for internal use.
/// </summary>
/// <returns></returns>
IWorkItemResult<TResult> GetWorkItemResultT<TResult>();
}
/// <summary>
/// IWorkItemResult interface.
/// Created when a WorkItemCallback work item is queued.
/// </summary>
public interface IWorkItemResult : IWorkItemResult<object>
{
}
/// <summary>
/// IWorkItemResult&lt;TResult&gt; interface.
/// Created when a Func&lt;TResult&gt; work item is queued.
/// </summary>
public interface IWorkItemResult<TResult> : IWaitableResult
{
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits.
/// </summary>
/// <returns>The result of the work item</returns>
TResult GetResult();
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout.
/// </summary>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
TResult GetResult(
int millisecondsTimeout,
bool exitContext);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout.
/// </summary>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
TResult GetResult(
TimeSpan timeout,
bool exitContext);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
/// </summary>
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
/// <param name="exitContext">
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
/// </param>
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException
TResult GetResult(
int millisecondsTimeout,
bool exitContext,
WaitHandle cancelWaitHandle);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
/// </summary>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException
TResult GetResult(
TimeSpan timeout,
bool exitContext,
WaitHandle cancelWaitHandle);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits.
/// </summary>
/// <param name="e">Filled with the exception if one was thrown</param>
/// <returns>The result of the work item</returns>
TResult GetResult(out Exception e);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout.
/// </summary>
/// <param name="millisecondsTimeout"></param>
/// <param name="exitContext"></param>
/// <param name="e">Filled with the exception if one was thrown</param>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
TResult GetResult(
int millisecondsTimeout,
bool exitContext,
out Exception e);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout.
/// </summary>
/// <param name="exitContext"></param>
/// <param name="e">Filled with the exception if one was thrown</param>
/// <param name="timeout"></param>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
TResult GetResult(
TimeSpan timeout,
bool exitContext,
out Exception e);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
/// </summary>
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
/// <param name="exitContext">
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
/// </param>
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
/// <param name="e">Filled with the exception if one was thrown</param>
/// <returns>The result of the work item</returns>
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException
TResult GetResult(
int millisecondsTimeout,
bool exitContext,
WaitHandle cancelWaitHandle,
out Exception e);
/// <summary>
/// Get the result of the work item.
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
/// </summary>
/// <returns>The result of the work item</returns>
/// <param name="cancelWaitHandle"></param>
/// <param name="e">Filled with the exception if one was thrown</param>
/// <param name="timeout"></param>
/// <param name="exitContext"></param>
/// On timeout throws WorkItemTimeoutException
/// On cancel throws WorkItemCancelException
TResult GetResult(
TimeSpan timeout,
bool exitContext,
WaitHandle cancelWaitHandle,
out Exception e);
/// <summary>
/// Gets an indication whether the asynchronous operation has completed.
/// </summary>
bool IsCompleted { get; }
/// <summary>
/// Gets an indication whether the asynchronous operation has been canceled.
/// </summary>
bool IsCanceled { get; }
/// <summary>
/// Gets the user-defined object that contains context data
/// for the work item method.
/// </summary>
object State { get; }
/// <summary>
/// Same as Cancel(false).
/// </summary>
bool Cancel();
/// <summary>
/// Cancel the work item execution.
/// If the work item is in the queue then it won't execute
/// If the work item is completed, it will remain completed
/// If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled
/// property to check if the work item has been cancelled. If the abortExecution is set to true then
/// the Smart Thread Pool will send an AbortException to the running thread to stop the execution
/// of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException.
/// If the work item is already cancelled it will remain cancelled
/// </summary>
/// <param name="abortExecution">When true send an AbortException to the executing thread.</param>
/// <returns>Returns true if the work item was not completed, otherwise false.</returns>
bool Cancel(bool abortExecution);
/// <summary>
/// Get the work item's priority
/// </summary>
WorkItemPriority WorkItemPriority { get; }
/// <summary>
/// Return the result, same as GetResult()
/// </summary>
TResult Result { get; }
/// <summary>
/// Returns the exception if occured otherwise returns null.
/// </summary>
object Exception { get; }
}
#endregion
#region .NET 3.5
// All these delegate are built-in .NET 3.5
// Comment/Remove them when compiling to .NET 3.5 to avoid ambiguity.
public delegate void Action();
public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T arg1);
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
#endregion
}

View File

@ -0,0 +1,27 @@

namespace Amib.Threading.Internal
{
/// <summary>
/// An internal delegate to call when the WorkItem starts or completes
/// </summary>
internal delegate void WorkItemStateCallback(WorkItem workItem);
internal interface IInternalWorkItemResult
{
event WorkItemStateCallback OnWorkItemStarted;
event WorkItemStateCallback OnWorkItemCompleted;
}
internal interface IInternalWaitableResult
{
/// <summary>
/// This method is intent for internal use.
/// </summary>
IWorkItemResult GetWorkItemResult();
}
public interface IHasWorkItemPriority
{
WorkItemPriority WorkItemPriority { get; }
}
}

View File

@ -1,240 +1,239 @@
// Ami Bar using System;
// amibar@gmail.com using System.Collections;
using System.Collections.Generic;
using System; using System.Diagnostics;
using System.Collections;
using System.Diagnostics; namespace Amib.Threading.Internal
{
namespace Amib.Threading.Internal #region PriorityQueue class
{
#region PriorityQueue class /// <summary>
/// PriorityQueue class
/// <summary> /// This class is not thread safe because we use external lock
/// PriorityQueue class /// </summary>
/// This class is not thread safe because we use external lock public sealed class PriorityQueue : IEnumerable
/// </summary> {
public sealed class PriorityQueue : IEnumerable #region Private members
{
#region Private members /// <summary>
/// The number of queues, there is one for each type of priority
/// <summary> /// </summary>
/// The number of queues, there is one for each type of priority private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
/// </summary>
private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1; /// <summary>
/// Work items queues. There is one for each type of priority
/// <summary> /// </summary>
/// Work items queues. There is one for each type of priority private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount];
/// </summary>
private Queue [] _queues = new Queue[_queuesCount]; /// <summary>
/// The total number of work items within the queues
/// <summary> /// </summary>
/// The total number of work items within the queues private int _workItemsCount;
/// </summary>
private int _workItemsCount = 0; /// <summary>
/// Use with IEnumerable interface
/// <summary> /// </summary>
/// Use with IEnumerable interface private int _version;
/// </summary>
private int _version = 0; #endregion
#endregion #region Contructor
#region Contructor public PriorityQueue()
{
public PriorityQueue() for(int i = 0; i < _queues.Length; ++i)
{ {
for(int i = 0; i < _queues.Length; ++i) _queues[i] = new LinkedList<IHasWorkItemPriority>();
{ }
_queues[i] = new Queue(); }
}
} #endregion
#endregion #region Methods
#region Methods /// <summary>
/// Enqueue a work item.
/// <summary> /// </summary>
/// Enqueue a work item. /// <param name="workItem">A work item</param>
/// </summary> public void Enqueue(IHasWorkItemPriority workItem)
/// <param name="workItem">A work item</param> {
public void Enqueue(IHasWorkItemPriority workItem) Debug.Assert(null != workItem);
{
Debug.Assert(null != workItem); int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
Debug.Assert(queueIndex >= 0);
int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1; Debug.Assert(queueIndex < _queuesCount);
Debug.Assert(queueIndex >= 0);
Debug.Assert(queueIndex < _queuesCount); _queues[queueIndex].AddLast(workItem);
++_workItemsCount;
_queues[queueIndex].Enqueue(workItem); ++_version;
++_workItemsCount; }
++_version;
} /// <summary>
/// Dequeque a work item.
/// <summary> /// </summary>
/// Dequeque a work item. /// <returns>Returns the next work item</returns>
/// </summary> public IHasWorkItemPriority Dequeue()
/// <returns>Returns the next work item</returns> {
public IHasWorkItemPriority Dequeue() IHasWorkItemPriority workItem = null;
{
IHasWorkItemPriority workItem = null; if(_workItemsCount > 0)
{
if(_workItemsCount > 0) int queueIndex = GetNextNonEmptyQueue(-1);
{ Debug.Assert(queueIndex >= 0);
int queueIndex = GetNextNonEmptyQueue(-1); workItem = _queues[queueIndex].First.Value;
Debug.Assert(queueIndex >= 0); _queues[queueIndex].RemoveFirst();
workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority; Debug.Assert(null != workItem);
Debug.Assert(null != workItem); --_workItemsCount;
--_workItemsCount; ++_version;
++_version; }
}
return workItem;
return workItem; }
}
/// <summary>
/// <summary> /// Find the next non empty queue starting at queue queueIndex+1
/// Find the next non empty queue starting at queue queueIndex+1 /// </summary>
/// </summary> /// <param name="queueIndex">The index-1 to start from</param>
/// <param name="queueIndex">The index-1 to start from</param> /// <returns>
/// <returns> /// The index of the next non empty queue or -1 if all the queues are empty
/// The index of the next non empty queue or -1 if all the queues are empty /// </returns>
/// </returns> private int GetNextNonEmptyQueue(int queueIndex)
private int GetNextNonEmptyQueue(int queueIndex) {
{ for(int i = queueIndex+1; i < _queuesCount; ++i)
for(int i = queueIndex+1; i < _queuesCount; ++i) {
{ if(_queues[i].Count > 0)
if(_queues[i].Count > 0) {
{ return i;
return i; }
} }
} return -1;
return -1; }
}
/// <summary>
/// <summary> /// The number of work items
/// The number of work items /// </summary>
/// </summary> public int Count
public int Count {
{ get
get {
{ return _workItemsCount;
return _workItemsCount; }
} }
}
/// <summary>
/// <summary> /// Clear all the work items
/// Clear all the work items /// </summary>
/// </summary> public void Clear()
public void Clear() {
{ if (_workItemsCount > 0)
if (_workItemsCount > 0) {
{ foreach(LinkedList<IHasWorkItemPriority> queue in _queues)
foreach(Queue queue in _queues) {
{ queue.Clear();
queue.Clear(); }
} _workItemsCount = 0;
_workItemsCount = 0; ++_version;
++_version; }
} }
}
#endregion
#endregion
#region IEnumerable Members
#region IEnumerable Members
/// <summary>
/// <summary> /// Returns an enumerator to iterate over the work items
/// Returns an enumerator to iterate over the work items /// </summary>
/// </summary> /// <returns>Returns an enumerator</returns>
/// <returns>Returns an enumerator</returns> public IEnumerator GetEnumerator()
public IEnumerator GetEnumerator() {
{ return new PriorityQueueEnumerator(this);
return new PriorityQueueEnumerator(this); }
}
#endregion
#endregion
#region PriorityQueueEnumerator
#region PriorityQueueEnumerator
/// <summary>
/// <summary> /// The class the implements the enumerator
/// The class the implements the enumerator /// </summary>
/// </summary> private class PriorityQueueEnumerator : IEnumerator
private class PriorityQueueEnumerator : IEnumerator {
{ private readonly PriorityQueue _priorityQueue;
private PriorityQueue _priorityQueue; private int _version;
private int _version; private int _queueIndex;
private int _queueIndex; private IEnumerator _enumerator;
private IEnumerator _enumerator;
public PriorityQueueEnumerator(PriorityQueue priorityQueue)
public PriorityQueueEnumerator(PriorityQueue priorityQueue) {
{ _priorityQueue = priorityQueue;
_priorityQueue = priorityQueue; _version = _priorityQueue._version;
_version = _priorityQueue._version; _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); if (_queueIndex >= 0)
if (_queueIndex >= 0) {
{ _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); }
} else
else {
{ _enumerator = null;
_enumerator = null; }
} }
}
#region IEnumerator Members
#region IEnumerator Members
public void Reset()
public void Reset() {
{ _version = _priorityQueue._version;
_version = _priorityQueue._version; _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); if (_queueIndex >= 0)
if (_queueIndex >= 0) {
{ _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); }
} else
else {
{ _enumerator = null;
_enumerator = null; }
} }
}
public object Current
public object Current {
{ get
get {
{ Debug.Assert(null != _enumerator);
Debug.Assert(null != _enumerator); return _enumerator.Current;
return _enumerator.Current; }
} }
}
public bool MoveNext()
public bool MoveNext() {
{ if (null == _enumerator)
if (null == _enumerator) {
{ return false;
return false; }
}
if(_version != _priorityQueue._version)
if(_version != _priorityQueue._version) {
{ throw new InvalidOperationException("The collection has been modified");
throw new InvalidOperationException("The collection has been modified");
}
} if (!_enumerator.MoveNext())
if (!_enumerator.MoveNext()) {
{ _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex); if(-1 == _queueIndex)
if(-1 == _queueIndex) {
{ return false;
return false; }
} _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); _enumerator.MoveNext();
_enumerator.MoveNext(); return true;
return true; }
} return true;
return true; }
}
#endregion
#endregion }
}
#endregion
#endregion }
}
#endregion
#endregion }
}

View File

@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Amib.Threading")]
[assembly: AssemblyDescription("Smart Thread Pool")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Amib.Threading")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("c764a3de-c4f8-434d-85b5-a09830d1e44f")]
[assembly: AssemblyVersion("2.2.3.0")]
#if (_PUBLISH)
[assembly: InternalsVisibleTo("STPTests,PublicKey=00240000048000009400000006020000002400005253413100040000010001004fe3d39add741ba7c8d52cd1eb0d94c7d79060ad956cbaff0e51c1dce94db10356b261778bc1ac3114b3218434da6fcd8416dd5507653809598f7d2afc422099ce4f6b7b0477f18e6c57c727ef2a7ab6ee56e6b4589fe44cb0e25f2875a3c65ab0383ee33c4dd93023f7ce1218bebc8b7a9a1dac878938f5c4f45ea74b6bd8ad")]
#else
[assembly: InternalsVisibleTo("STPTests")]
#endif

16
ThirdParty/SmartThreadPool/SLExt.cs vendored Normal file
View File

@ -0,0 +1,16 @@
#if _SILVERLIGHT
using System.Threading;
namespace Amib.Threading
{
public enum ThreadPriority
{
Lowest,
BelowNormal,
Normal,
AboveNormal,
Highest,
}
}
#endif

View File

@ -0,0 +1,62 @@
#if !(_WINDOWS_CE)
using System;
using System.Threading;
namespace Amib.Threading.Internal
{
#if _WINDOWS || WINDOWS_PHONE
internal static class STPEventWaitHandle
{
public const int WaitTimeout = Timeout.Infinite;
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout);
}
internal static int WaitAny(WaitHandle[] waitHandles)
{
return WaitHandle.WaitAny(waitHandles);
}
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout);
}
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
{
return waitHandle.WaitOne(millisecondsTimeout);
}
}
#else
internal static class STPEventWaitHandle
{
public const int WaitTimeout = Timeout.Infinite;
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
}
internal static int WaitAny(WaitHandle[] waitHandles)
{
return WaitHandle.WaitAny(waitHandles);
}
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
{
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
}
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
{
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
}
}
#endif
}
#endif

View File

@ -1,354 +1,448 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
namespace Amib.Threading.Internal
{ namespace Amib.Threading
internal enum STPPerformanceCounterType {
{ public interface ISTPPerformanceCountersReader
// Fields {
ActiveThreads = 0, long InUseThreads { get; }
InUseThreads = 1, long ActiveThreads { get; }
OverheadThreads = 2, long WorkItemsQueued { get; }
OverheadThreadsPercent = 3, long WorkItemsProcessed { get; }
OverheadThreadsPercentBase = 4, }
}
WorkItems = 5,
WorkItemsInQueue = 6, namespace Amib.Threading.Internal
WorkItemsProcessed = 7, {
internal interface ISTPInstancePerformanceCounters : IDisposable
WorkItemsQueuedPerSecond = 8, {
WorkItemsProcessedPerSecond = 9, void Close();
void SampleThreads(long activeThreads, long inUseThreads);
AvgWorkItemWaitTime = 10, void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
AvgWorkItemWaitTimeBase = 11, void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
AvgWorkItemProcessTime = 12, }
AvgWorkItemProcessTimeBase = 13, #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
WorkItemsGroups = 14, internal enum STPPerformanceCounterType
{
LastCounter = 14, // Fields
} ActiveThreads = 0,
InUseThreads = 1,
OverheadThreads = 2,
/// <summary> OverheadThreadsPercent = 3,
/// Summary description for STPPerformanceCounter. OverheadThreadsPercentBase = 4,
/// </summary>
internal class STPPerformanceCounter WorkItems = 5,
{ WorkItemsInQueue = 6,
// Fields WorkItemsProcessed = 7,
private PerformanceCounterType _pcType;
protected string _counterHelp; WorkItemsQueuedPerSecond = 8,
protected string _counterName; WorkItemsProcessedPerSecond = 9,
// Methods AvgWorkItemWaitTime = 10,
public STPPerformanceCounter( AvgWorkItemWaitTimeBase = 11,
string counterName,
string counterHelp, AvgWorkItemProcessTime = 12,
PerformanceCounterType pcType) AvgWorkItemProcessTimeBase = 13,
{
this._counterName = counterName; WorkItemsGroups = 14,
this._counterHelp = counterHelp;
this._pcType = pcType; LastCounter = 14,
} }
public void AddCounterToCollection(CounterCreationDataCollection counterData)
{ /// <summary>
CounterCreationData counterCreationData = new CounterCreationData( /// Summary description for STPPerformanceCounter.
_counterName, /// </summary>
_counterHelp, internal class STPPerformanceCounter
_pcType); {
// Fields
counterData.Add(counterCreationData); private readonly PerformanceCounterType _pcType;
} protected string _counterHelp;
protected string _counterName;
// Properties
public string Name // Methods
{ public STPPerformanceCounter(
get string counterName,
{ string counterHelp,
return _counterName; PerformanceCounterType pcType)
} {
} _counterName = counterName;
} _counterHelp = counterHelp;
_pcType = pcType;
internal class STPPerformanceCounters }
{
// Fields public void AddCounterToCollection(CounterCreationDataCollection counterData)
internal STPPerformanceCounter[] _stpPerformanceCounters; {
private static STPPerformanceCounters _instance; CounterCreationData counterCreationData = new CounterCreationData(
internal const string _stpCategoryHelp = "SmartThreadPool performance counters"; _counterName,
internal const string _stpCategoryName = "SmartThreadPool"; _counterHelp,
_pcType);
// Methods
static STPPerformanceCounters() counterData.Add(counterCreationData);
{ }
_instance = new STPPerformanceCounters();
} // Properties
public string Name
private STPPerformanceCounters() {
{ get
STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[] {
{ return _counterName;
new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32), }
new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32), }
new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32), }
new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase), internal class STPPerformanceCounters
{
new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32), // Fields
new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32), internal STPPerformanceCounter[] _stpPerformanceCounters;
new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32), private static readonly STPPerformanceCounters _instance;
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32), internal const string _stpCategoryName = "SmartThreadPool";
new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
// Methods
new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64), static STPPerformanceCounters()
new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase), {
_instance = new STPPerformanceCounters();
new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64), }
new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
private STPPerformanceCounters()
new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32), {
}; STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
{
_stpPerformanceCounters = stpPerformanceCounters; new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
SetupCategory(); new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
} new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
private void SetupCategory() new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
{
if (!PerformanceCounterCategory.Exists(_stpCategoryName)) new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
{ new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
CounterCreationDataCollection counters = new CounterCreationDataCollection(); new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
for (int i = 0; i < _stpPerformanceCounters.Length; i++) new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
{ new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
_stpPerformanceCounters[i].AddCounterToCollection(counters);
} new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64),
new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase),
// *********** Remark for .NET 2.0 *********** new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
// If you are here, it means you got the warning that this overload new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
// of the method is deprecated in .NET 2.0. To use the correct
// method overload, uncomment the third argument of new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
// the method. };
#pragma warning disable 0618
PerformanceCounterCategory.Create( _stpPerformanceCounters = stpPerformanceCounters;
_stpCategoryName, SetupCategory();
_stpCategoryHelp, }
//PerformanceCounterCategoryType.MultiInstance,
counters); private void SetupCategory()
#pragma warning restore 0618 {
} if (!PerformanceCounterCategory.Exists(_stpCategoryName))
} {
CounterCreationDataCollection counters = new CounterCreationDataCollection();
// Properties
public static STPPerformanceCounters Instance for (int i = 0; i < _stpPerformanceCounters.Length; i++)
{ {
get _stpPerformanceCounters[i].AddCounterToCollection(counters);
{ }
return _instance;
} PerformanceCounterCategory.Create(
} _stpCategoryName,
} _stpCategoryHelp,
PerformanceCounterCategoryType.MultiInstance,
internal class STPInstancePerformanceCounter : IDisposable counters);
{
// Fields }
private PerformanceCounter _pcs; }
// Methods // Properties
protected STPInstancePerformanceCounter() public static STPPerformanceCounters Instance
{ {
} get
{
public STPInstancePerformanceCounter( return _instance;
string instance, }
STPPerformanceCounterType spcType) }
{ }
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
_pcs = new PerformanceCounter( internal class STPInstancePerformanceCounter : IDisposable
STPPerformanceCounters._stpCategoryName, {
counters._stpPerformanceCounters[(int) spcType].Name, // Fields
instance, private bool _isDisposed;
false); private PerformanceCounter _pcs;
_pcs.RawValue = _pcs.RawValue;
} // Methods
protected STPInstancePerformanceCounter()
~STPInstancePerformanceCounter() {
{ _isDisposed = false;
Close(); }
}
public STPInstancePerformanceCounter(
public void Close() string instance,
{ STPPerformanceCounterType spcType) : this()
if (_pcs != null) {
{ STPPerformanceCounters counters = STPPerformanceCounters.Instance;
_pcs.RemoveInstance(); _pcs = new PerformanceCounter(
_pcs.Close(); STPPerformanceCounters._stpCategoryName,
_pcs = null; counters._stpPerformanceCounters[(int) spcType].Name,
} instance,
} false);
_pcs.RawValue = _pcs.RawValue;
public void Dispose() }
{
Close();
GC.SuppressFinalize(this); public void Close()
} {
if (_pcs != null)
public virtual void Increment() {
{ _pcs.RemoveInstance();
_pcs.Increment(); _pcs.Close();
} _pcs = null;
}
public virtual void IncrementBy(long val) }
{
_pcs.IncrementBy(val); public void Dispose()
} {
Dispose(true);
public virtual void Set(long val) }
{
_pcs.RawValue = val; public virtual void Dispose(bool disposing)
} {
} if (!_isDisposed)
{
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter if (disposing)
{ {
// Methods Close();
public STPInstanceNullPerformanceCounter() {} }
public override void Increment() {} }
public override void IncrementBy(long value) {} _isDisposed = true;
public override void Set(long val) {} }
}
public virtual void Increment()
internal interface ISTPInstancePerformanceCounters : IDisposable {
{ _pcs.Increment();
void Close(); }
void SampleThreads(long activeThreads, long inUseThreads);
void SampleWorkItems(long workItemsQueued, long workItemsProcessed); public virtual void IncrementBy(long val)
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime); {
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime); _pcs.IncrementBy(val);
} }
public virtual void Set(long val)
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable {
{ _pcs.RawValue = val;
// Fields }
private STPInstancePerformanceCounter[] _pcs; }
private static STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
// Methods {
static STPInstancePerformanceCounters() // Methods
{ public override void Increment() {}
_stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter(); public override void IncrementBy(long value) {}
} public override void Set(long val) {}
}
public STPInstancePerformanceCounters(string instance)
{
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
// STPPerformanceCounters counters = STPPerformanceCounters.Instance; internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters
for (int i = 0; i < _pcs.Length; i++) {
{ private bool _isDisposed;
if (instance != null) // Fields
{ private STPInstancePerformanceCounter[] _pcs;
_pcs[i] = new STPInstancePerformanceCounter( private static readonly STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
instance,
(STPPerformanceCounterType) i); // Methods
} static STPInstancePerformanceCounters()
else {
{ _stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
_pcs[i] = _stpInstanceNullPerformanceCounter; }
}
} public STPInstancePerformanceCounters(string instance)
} {
_isDisposed = false;
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
public void Close()
{ // Call the STPPerformanceCounters.Instance so the static constructor will
if (null != _pcs) // intialize the STPPerformanceCounters singleton.
{ STPPerformanceCounters.Instance.GetHashCode();
for (int i = 0; i < _pcs.Length; i++)
{ for (int i = 0; i < _pcs.Length; i++)
if (null != _pcs[i]) {
{ if (instance != null)
_pcs[i].Close(); {
} _pcs[i] = new STPInstancePerformanceCounter(
} instance,
_pcs = null; (STPPerformanceCounterType) i);
} }
} else
{
~STPInstancePerformanceCounters() _pcs[i] = _stpInstanceNullPerformanceCounter;
{ }
Close(); }
} }
public void Dispose()
{ public void Close()
Close(); {
GC.SuppressFinalize(this); if (null != _pcs)
} {
for (int i = 0; i < _pcs.Length; i++)
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType) {
{ if (null != _pcs[i])
return _pcs[(int) spcType]; {
} _pcs[i].Dispose();
}
public void SampleThreads(long activeThreads, long inUseThreads) }
{ _pcs = null;
GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads); }
GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads); }
GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
public void Dispose()
GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads); {
GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads); Dispose(true);
} }
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) public virtual void Dispose(bool disposing)
{ {
GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed); if (!_isDisposed)
GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued); {
GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed); if (disposing)
{
GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued); Close();
GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed); }
} }
_isDisposed = true;
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) }
{
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds); private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment(); {
} return _pcs[(int) spcType];
}
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
{ public void SampleThreads(long activeThreads, long inUseThreads)
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds); {
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment(); GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
} GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
} GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
{ GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
static NullSTPInstancePerformanceCounters() }
{
} public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
{
private static NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(null); GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
public static NullSTPInstancePerformanceCounters Instance GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
{
get { return _instance; } GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
} GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
}
public NullSTPInstancePerformanceCounters(string instance) {}
public void Close() {} public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
public void Dispose() {} {
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
public void SampleThreads(long activeThreads, long inUseThreads) {} GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {} }
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {} public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
} {
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
} GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
}
}
#endif
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
{
private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters();
public static NullSTPInstancePerformanceCounters Instance
{
get { return _instance; }
}
public void Close() {}
public void Dispose() {}
public void SampleThreads(long activeThreads, long inUseThreads) {}
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
public long InUseThreads
{
get { return 0; }
}
public long ActiveThreads
{
get { return 0; }
}
public long WorkItemsQueued
{
get { return 0; }
}
public long WorkItemsProcessed
{
get { return 0; }
}
}
internal class LocalSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
{
public void Close() { }
public void Dispose() { }
private long _activeThreads;
private long _inUseThreads;
private long _workItemsQueued;
private long _workItemsProcessed;
public long InUseThreads
{
get { return _inUseThreads; }
}
public long ActiveThreads
{
get { return _activeThreads; }
}
public long WorkItemsQueued
{
get { return _workItemsQueued; }
}
public long WorkItemsProcessed
{
get { return _workItemsProcessed; }
}
public void SampleThreads(long activeThreads, long inUseThreads)
{
_activeThreads = activeThreads;
_inUseThreads = inUseThreads;
}
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
{
_workItemsQueued = workItemsQueued;
_workItemsProcessed = workItemsProcessed;
}
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
{
// Not supported
}
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
{
// Not supported
}
}
}

View File

@ -1,113 +1,212 @@
// Ami Bar using System;
// amibar@gmail.com using System.Threading;
using System.Threading; namespace Amib.Threading
{
namespace Amib.Threading /// <summary>
{ /// Summary description for STPStartInfo.
/// <summary> /// </summary>
/// Summary description for STPStartInfo. public class STPStartInfo : WIGStartInfo
/// </summary> {
public class STPStartInfo : WIGStartInfo private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
{ private int _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
/// <summary> private int _maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
/// Idle timeout in milliseconds. #if !(WINDOWS_PHONE)
/// If a thread is idle for _idleTimeout milliseconds then private ThreadPriority _threadPriority = SmartThreadPool.DefaultThreadPriority;
/// it may quit. #endif
/// </summary> private string _performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
private int _idleTimeout; private bool _areThreadsBackground = SmartThreadPool.DefaultAreThreadsBackground;
private bool _enableLocalPerformanceCounters;
/// <summary> private string _threadPoolName = SmartThreadPool.DefaultThreadPoolName;
/// The lower limit of threads in the pool. private int? _maxStackSize = SmartThreadPool.DefaultMaxStackSize;
/// </summary>
private int _minWorkerThreads; public STPStartInfo()
{
/// <summary> _performanceCounterInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
/// The upper limit of threads in the pool. #if !(WINDOWS_PHONE)
/// </summary> _threadPriority = SmartThreadPool.DefaultThreadPriority;
private int _maxWorkerThreads; #endif
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
/// <summary> _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
/// The priority of the threads in the pool _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
/// </summary> }
private ThreadPriority _threadPriority;
public STPStartInfo(STPStartInfo stpStartInfo)
/// <summary> : base(stpStartInfo)
/// The thread pool name. Threads will get names depending on this. {
/// </summary> _idleTimeout = stpStartInfo.IdleTimeout;
private string _threadPoolName; _minWorkerThreads = stpStartInfo.MinWorkerThreads;
_maxWorkerThreads = stpStartInfo.MaxWorkerThreads;
/// <summary> #if !(WINDOWS_PHONE)
/// If this field is not null then the performance counters are enabled _threadPriority = stpStartInfo.ThreadPriority;
/// and use the string as the name of the instance. #endif
/// </summary> _performanceCounterInstanceName = stpStartInfo.PerformanceCounterInstanceName;
private string _pcInstanceName; _enableLocalPerformanceCounters = stpStartInfo._enableLocalPerformanceCounters;
_threadPoolName = stpStartInfo._threadPoolName;
private int _stackSize; _areThreadsBackground = stpStartInfo.AreThreadsBackground;
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
public STPStartInfo() : base() _apartmentState = stpStartInfo._apartmentState;
{ #endif
_idleTimeout = SmartThreadPool.DefaultIdleTimeout; }
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads; /// <summary>
_threadPriority = SmartThreadPool.DefaultThreadPriority; /// Get/Set the idle timeout in milliseconds.
_threadPoolName = SmartThreadPool.DefaultThreadPoolName; /// If a thread is idle (starved) longer than IdleTimeout then it may quit.
_pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName; /// </summary>
_stackSize = SmartThreadPool.DefaultStackSize; public virtual int IdleTimeout
} {
get { return _idleTimeout; }
public STPStartInfo(STPStartInfo stpStartInfo) : base(stpStartInfo) set
{ {
_idleTimeout = stpStartInfo._idleTimeout; ThrowIfReadOnly();
_minWorkerThreads = stpStartInfo._minWorkerThreads; _idleTimeout = value;
_maxWorkerThreads = stpStartInfo._maxWorkerThreads; }
_threadPriority = stpStartInfo._threadPriority; }
_threadPoolName = stpStartInfo._threadPoolName;
_pcInstanceName = stpStartInfo._pcInstanceName;
_stackSize = stpStartInfo._stackSize; /// <summary>
} /// Get/Set the lower limit of threads in the pool.
/// </summary>
public int IdleTimeout public virtual int MinWorkerThreads
{ {
get { return _idleTimeout; } get { return _minWorkerThreads; }
set { _idleTimeout = value; } set
} {
ThrowIfReadOnly();
public int MinWorkerThreads _minWorkerThreads = value;
{ }
get { return _minWorkerThreads; } }
set { _minWorkerThreads = value; }
}
/// <summary>
public int MaxWorkerThreads /// Get/Set the upper limit of threads in the pool.
{ /// </summary>
get { return _maxWorkerThreads; } public virtual int MaxWorkerThreads
set { _maxWorkerThreads = value; } {
} get { return _maxWorkerThreads; }
set
public ThreadPriority ThreadPriority {
{ ThrowIfReadOnly();
get { return _threadPriority; } _maxWorkerThreads = value;
set { _threadPriority = value; } }
} }
public virtual string ThreadPoolName #if !(WINDOWS_PHONE)
{ /// <summary>
get { return _threadPoolName; } /// Get/Set the scheduling priority of the threads in the pool.
set { _threadPoolName = value; } /// The Os handles the scheduling.
} /// </summary>
public virtual ThreadPriority ThreadPriority
{
public string PerformanceCounterInstanceName get { return _threadPriority; }
{ set
get { return _pcInstanceName; } {
set { _pcInstanceName = value; } ThrowIfReadOnly();
} _threadPriority = value;
}
public int StackSize }
{ #endif
get { return _stackSize; } /// <summary>
set { _stackSize = value; } /// Get/Set the thread pool name. Threads will get names depending on this.
} /// </summary>
} public virtual string ThreadPoolName {
} get { return _threadPoolName; }
set
{
ThrowIfReadOnly ();
_threadPoolName = value;
}
}
/// <summary>
/// Get/Set the performance counter instance name of this SmartThreadPool
/// The default is null which indicate not to use performance counters at all.
/// </summary>
public virtual string PerformanceCounterInstanceName
{
get { return _performanceCounterInstanceName; }
set
{
ThrowIfReadOnly();
_performanceCounterInstanceName = value;
}
}
/// <summary>
/// Enable/Disable the local performance counter.
/// This enables the user to get some performance information about the SmartThreadPool
/// without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.)
/// The default is false.
/// </summary>
public virtual bool EnableLocalPerformanceCounters
{
get { return _enableLocalPerformanceCounters; }
set
{
ThrowIfReadOnly();
_enableLocalPerformanceCounters = value;
}
}
/// <summary>
/// Get/Set backgroundness of thread in thread pool.
/// </summary>
public virtual bool AreThreadsBackground
{
get { return _areThreadsBackground; }
set
{
ThrowIfReadOnly ();
_areThreadsBackground = value;
}
}
/// <summary>
/// Get a readonly version of this STPStartInfo.
/// </summary>
/// <returns>Returns a readonly reference to this STPStartInfo</returns>
public new STPStartInfo AsReadOnly()
{
return new STPStartInfo(this) { _readOnly = true };
}
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
private ApartmentState _apartmentState = SmartThreadPool.DefaultApartmentState;
/// <summary>
/// Get/Set the apartment state of threads in the thread pool
/// </summary>
public ApartmentState ApartmentState
{
get { return _apartmentState; }
set
{
ThrowIfReadOnly();
_apartmentState = value;
}
}
#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
/// <summary>
/// Get/Set the max stack size of threads in the thread pool
/// </summary>
public int? MaxStackSize
{
get { return _maxStackSize; }
set
{
ThrowIfReadOnly();
if (value.HasValue && value.Value < 0)
{
throw new ArgumentOutOfRangeException("value", "Value must be greater than 0.");
}
_maxStackSize = value;
}
}
#endif
#endif
}
}

View File

@ -0,0 +1,60 @@

using System;
using Amib.Threading.Internal;
namespace Amib.Threading
{
public partial class SmartThreadPool
{
#region ThreadEntry class
internal class ThreadEntry
{
/// <summary>
/// The thread creation time
/// The value is stored as UTC value.
/// </summary>
private readonly DateTime _creationTime;
/// <summary>
/// The last time this thread has been running
/// It is updated by IAmAlive() method
/// The value is stored as UTC value.
/// </summary>
private DateTime _lastAliveTime;
/// <summary>
/// A reference from each thread in the thread pool to its SmartThreadPool
/// object container.
/// With this variable a thread can know whatever it belongs to a
/// SmartThreadPool.
/// </summary>
private readonly SmartThreadPool _associatedSmartThreadPool;
/// <summary>
/// A reference to the current work item a thread from the thread pool
/// is executing.
/// </summary>
public WorkItem CurrentWorkItem { get; set; }
public ThreadEntry(SmartThreadPool stp)
{
_associatedSmartThreadPool = stp;
_creationTime = DateTime.UtcNow;
_lastAliveTime = DateTime.MinValue;
}
public SmartThreadPool AssociatedSmartThreadPool
{
get { return _associatedSmartThreadPool; }
}
public void IAmAlive()
{
_lastAliveTime = DateTime.UtcNow;
}
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
using System.Collections.Generic;
namespace Amib.Threading.Internal
{
internal class SynchronizedDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> _dictionary;
private readonly object _lock;
public SynchronizedDictionary()
{
_lock = new object();
_dictionary = new Dictionary<TKey, TValue>();
}
public int Count
{
get { return _dictionary.Count; }
}
public bool Contains(TKey key)
{
lock (_lock)
{
return _dictionary.ContainsKey(key);
}
}
public void Remove(TKey key)
{
lock (_lock)
{
_dictionary.Remove(key);
}
}
public object SyncRoot
{
get { return _lock; }
}
public TValue this[TKey key]
{
get
{
lock (_lock)
{
return _dictionary[key];
}
}
set
{
lock (_lock)
{
_dictionary[key] = value;
}
}
}
public Dictionary<TKey, TValue>.KeyCollection Keys
{
get
{
lock (_lock)
{
return _dictionary.Keys;
}
}
}
public Dictionary<TKey, TValue>.ValueCollection Values
{
get
{
lock (_lock)
{
return _dictionary.Values;
}
}
}
public void Clear()
{
lock (_lock)
{
_dictionary.Clear();
}
}
}
}

View File

@ -1,99 +1,171 @@
// Ami Bar using System;
// amibar@gmail.com
namespace Amib.Threading
namespace Amib.Threading {
{ /// <summary>
/// <summary> /// Summary description for WIGStartInfo.
/// Summary description for WIGStartInfo. /// </summary>
/// </summary> public class WIGStartInfo
public class WIGStartInfo {
{ private bool _useCallerCallContext;
/// <summary> private bool _useCallerHttpContext;
/// Use the caller's security context private bool _disposeOfStateObjects;
/// </summary> private CallToPostExecute _callToPostExecute;
private bool _useCallerCallContext; private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
private bool _startSuspended;
/// <summary> private WorkItemPriority _workItemPriority;
/// Use the caller's HTTP context private bool _fillStateWithArgs;
/// </summary>
private bool _useCallerHttpContext; protected bool _readOnly;
/// <summary> public WIGStartInfo()
/// Dispose of the state object of a work item {
/// </summary> _fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
private bool _disposeOfStateObjects; _workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
_startSuspended = SmartThreadPool.DefaultStartSuspended;
/// <summary> _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
/// The option to run the post execute _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
/// </summary> _disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
private CallToPostExecute _callToPostExecute; _useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
/// <summary> }
/// A post execute callback to call when none is provided in
/// the QueueWorkItem method. public WIGStartInfo(WIGStartInfo wigStartInfo)
/// </summary> {
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback; _useCallerCallContext = wigStartInfo.UseCallerCallContext;
_useCallerHttpContext = wigStartInfo.UseCallerHttpContext;
/// <summary> _disposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
/// Indicate the WorkItemsGroup to suspend the handling of the work items _callToPostExecute = wigStartInfo.CallToPostExecute;
/// until the Start() method is called. _postExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
/// </summary> _workItemPriority = wigStartInfo.WorkItemPriority;
private bool _startSuspended; _startSuspended = wigStartInfo.StartSuspended;
_fillStateWithArgs = wigStartInfo.FillStateWithArgs;
public WIGStartInfo() }
{
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext; protected void ThrowIfReadOnly()
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext; {
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects; if (_readOnly)
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute; {
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback; throw new NotSupportedException("This is a readonly instance and set is not supported");
_startSuspended = SmartThreadPool.DefaultStartSuspended; }
} }
public WIGStartInfo(WIGStartInfo wigStartInfo) /// <summary>
{ /// Get/Set if to use the caller's security context
_useCallerCallContext = wigStartInfo._useCallerCallContext; /// </summary>
_useCallerHttpContext = wigStartInfo._useCallerHttpContext; public virtual bool UseCallerCallContext
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects; {
_callToPostExecute = wigStartInfo._callToPostExecute; get { return _useCallerCallContext; }
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback; set
_startSuspended = wigStartInfo._startSuspended; {
} ThrowIfReadOnly();
_useCallerCallContext = value;
public bool UseCallerCallContext }
{ }
get { return _useCallerCallContext; }
set { _useCallerCallContext = value; }
} /// <summary>
/// Get/Set if to use the caller's HTTP context
public bool UseCallerHttpContext /// </summary>
{ public virtual bool UseCallerHttpContext
get { return _useCallerHttpContext; } {
set { _useCallerHttpContext = value; } get { return _useCallerHttpContext; }
} set
{
public bool DisposeOfStateObjects ThrowIfReadOnly();
{ _useCallerHttpContext = value;
get { return _disposeOfStateObjects; } }
set { _disposeOfStateObjects = value; } }
}
public CallToPostExecute CallToPostExecute /// <summary>
{ /// Get/Set if to dispose of the state object of a work item
get { return _callToPostExecute; } /// </summary>
set { _callToPostExecute = value; } public virtual bool DisposeOfStateObjects
} {
get { return _disposeOfStateObjects; }
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback set
{ {
get { return _postExecuteWorkItemCallback; } ThrowIfReadOnly();
set { _postExecuteWorkItemCallback = value; } _disposeOfStateObjects = value;
} }
}
public bool StartSuspended
{
get { return _startSuspended; } /// <summary>
set { _startSuspended = value; } /// Get/Set the run the post execute options
} /// </summary>
} public virtual CallToPostExecute CallToPostExecute
} {
get { return _callToPostExecute; }
set
{
ThrowIfReadOnly();
_callToPostExecute = value;
}
}
/// <summary>
/// Get/Set the default post execute callback
/// </summary>
public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback
{
get { return _postExecuteWorkItemCallback; }
set
{
ThrowIfReadOnly();
_postExecuteWorkItemCallback = value;
}
}
/// <summary>
/// Get/Set if the work items execution should be suspended until the Start()
/// method is called.
/// </summary>
public virtual bool StartSuspended
{
get { return _startSuspended; }
set
{
ThrowIfReadOnly();
_startSuspended = value;
}
}
/// <summary>
/// Get/Set the default priority that a work item gets when it is enqueued
/// </summary>
public virtual WorkItemPriority WorkItemPriority
{
get { return _workItemPriority; }
set { _workItemPriority = value; }
}
/// <summary>
/// Get/Set the if QueueWorkItem of Action&lt;...&gt;/Func&lt;...&gt; fill the
/// arguments as an object array into the state of the work item.
/// The arguments can be access later by IWorkItemResult.State.
/// </summary>
public virtual bool FillStateWithArgs
{
get { return _fillStateWithArgs; }
set
{
ThrowIfReadOnly();
_fillStateWithArgs = value;
}
}
/// <summary>
/// Get a readonly version of this WIGStartInfo
/// </summary>
/// <returns>Returns a readonly reference to this WIGStartInfoRO</returns>
public WIGStartInfo AsReadOnly()
{
return new WIGStartInfo(this) { _readOnly = true };
}
}
}

View File

@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Amib.Threading.Internal
{
public partial class WorkItem
{
#region WorkItemResult class
private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult, IInternalWaitableResult
{
/// <summary>
/// A back reference to the work item
/// </summary>
private readonly WorkItem _workItem;
public WorkItemResult(WorkItem workItem)
{
_workItem = workItem;
}
internal WorkItem GetWorkItem()
{
return _workItem;
}
#region IWorkItemResult Members
public bool IsCompleted
{
get
{
return _workItem.IsCompleted;
}
}
public bool IsCanceled
{
get
{
return _workItem.IsCanceled;
}
}
public object GetResult()
{
return _workItem.GetResult(Timeout.Infinite, true, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null);
}
public object GetResult(TimeSpan timeout, bool exitContext)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
}
public object GetResult(out Exception e)
{
return _workItem.GetResult(Timeout.Infinite, true, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
}
public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
}
public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
}
public bool Cancel()
{
return Cancel(false);
}
public bool Cancel(bool abortExecution)
{
return _workItem.Cancel(abortExecution);
}
public object State
{
get
{
return _workItem._state;
}
}
public WorkItemPriority WorkItemPriority
{
get
{
return _workItem._workItemInfo.WorkItemPriority;
}
}
/// <summary>
/// Return the result, same as GetResult()
/// </summary>
public object Result
{
get { return GetResult(); }
}
/// <summary>
/// Returns the exception if occured otherwise returns null.
/// This value is valid only after the work item completed,
/// before that it is always null.
/// </summary>
public object Exception
{
get { return _workItem._exception; }
}
#endregion
#region IInternalWorkItemResult Members
public event WorkItemStateCallback OnWorkItemStarted
{
add
{
_workItem.OnWorkItemStarted += value;
}
remove
{
_workItem.OnWorkItemStarted -= value;
}
}
public event WorkItemStateCallback OnWorkItemCompleted
{
add
{
_workItem.OnWorkItemCompleted += value;
}
remove
{
_workItem.OnWorkItemCompleted -= value;
}
}
#endregion
#region IInternalWorkItemResult Members
public IWorkItemResult GetWorkItemResult()
{
return this;
}
public IWorkItemResult<TResult> GetWorkItemResultT<TResult>()
{
return new WorkItemResultTWrapper<TResult>(this);
}
#endregion
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,333 +1,343 @@
// Ami Bar using System;
// amibar@gmail.com
namespace Amib.Threading.Internal
using System; {
#region WorkItemFactory class
namespace Amib.Threading.Internal
{ public class WorkItemFactory
#region WorkItemFactory class {
/// <summary>
public class WorkItemFactory /// Create a new work item
{ /// </summary>
/// <summary> /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
/// Create a new work item /// <param name="wigStartInfo">Work item group start information</param>
/// </summary> /// <param name="callback">A callback to execute</param>
/// <param name="wigStartInfo">Work item group start information</param> /// <returns>Returns a work item</returns>
/// <param name="callback">A callback to execute</param> public static WorkItem CreateWorkItem(
/// <returns>Returns a work item</returns> IWorkItemsGroup workItemsGroup,
public static WorkItem CreateWorkItem( WIGStartInfo wigStartInfo,
IWorkItemsGroup workItemsGroup, WorkItemCallback callback)
WIGStartInfo wigStartInfo, {
WorkItemCallback callback) return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
{ }
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
} /// <summary>
/// Create a new work item
/// <summary> /// </summary>
/// Create a new work item /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
/// </summary> /// <param name="wigStartInfo">Work item group start information</param>
/// <param name="wigStartInfo">Work item group start information</param> /// <param name="callback">A callback to execute</param>
/// <param name="callback">A callback to execute</param> /// <param name="workItemPriority">The priority of the work item</param>
/// <param name="workItemPriority">The priority of the work item</param> /// <returns>Returns a work item</returns>
/// <returns>Returns a work item</returns> public static WorkItem CreateWorkItem(
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup,
IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
WIGStartInfo wigStartInfo, WorkItemCallback callback,
WorkItemCallback callback, WorkItemPriority workItemPriority)
WorkItemPriority workItemPriority) {
{ return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority); }
}
/// <summary>
/// <summary> /// Create a new work item
/// Create a new work item /// </summary>
/// </summary> /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
/// <param name="wigStartInfo">Work item group start information</param> /// <param name="wigStartInfo">Work item group start information</param>
/// <param name="workItemInfo">Work item info</param> /// <param name="workItemInfo">Work item info</param>
/// <param name="callback">A callback to execute</param> /// <param name="callback">A callback to execute</param>
/// <returns>Returns a work item</returns> /// <returns>Returns a work item</returns>
public static WorkItem CreateWorkItem( public static WorkItem CreateWorkItem(
IWorkItemsGroup workItemsGroup, IWorkItemsGroup workItemsGroup,
WIGStartInfo wigStartInfo, WIGStartInfo wigStartInfo,
WorkItemInfo workItemInfo, WorkItemInfo workItemInfo,
WorkItemCallback callback) WorkItemCallback callback)
{ {
return CreateWorkItem( return CreateWorkItem(
workItemsGroup, workItemsGroup,
wigStartInfo, wigStartInfo,
workItemInfo, workItemInfo,
callback, callback,
null); null);
} }
/// <summary> /// <summary>
/// Create a new work item /// Create a new work item
/// </summary> /// </summary>
/// <param name="wigStartInfo">Work item group start information</param> /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
/// <param name="callback">A callback to execute</param> /// <param name="wigStartInfo">Work item group start information</param>
/// <param name="state"> /// <param name="callback">A callback to execute</param>
/// The context object of the work item. Used for passing arguments to the work item. /// <param name="state">
/// </param> /// The context object of the work item. Used for passing arguments to the work item.
/// <returns>Returns a work item</returns> /// </param>
public static WorkItem CreateWorkItem( /// <returns>Returns a work item</returns>
IWorkItemsGroup workItemsGroup, public static WorkItem CreateWorkItem(
WIGStartInfo wigStartInfo, IWorkItemsGroup workItemsGroup,
WorkItemCallback callback, WIGStartInfo wigStartInfo,
object state) WorkItemCallback callback,
{ object state)
ValidateCallback(callback); {
ValidateCallback(callback);
WorkItemInfo workItemInfo = new WorkItemInfo();
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; WorkItemInfo workItemInfo = new WorkItemInfo();
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback; workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
WorkItem workItem = new WorkItem( workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
workItemsGroup,
workItemInfo, WorkItem workItem = new WorkItem(
callback, workItemsGroup,
state); workItemInfo,
return workItem; callback,
} state);
return workItem;
/// <summary> }
/// Create a new work item
/// </summary> /// <summary>
/// <param name="wigStartInfo">Work item group start information</param> /// Create a new work item
/// <param name="callback">A callback to execute</param> /// </summary>
/// <param name="state"> /// <param name="workItemsGroup">The work items group</param>
/// The context object of the work item. Used for passing arguments to the work item. /// <param name="wigStartInfo">Work item group start information</param>
/// </param> /// <param name="callback">A callback to execute</param>
/// <param name="workItemPriority">The work item priority</param> /// <param name="state">
/// <returns>Returns a work item</returns> /// The context object of the work item. Used for passing arguments to the work item.
public static WorkItem CreateWorkItem( /// </param>
IWorkItemsGroup workItemsGroup, /// <param name="workItemPriority">The work item priority</param>
WIGStartInfo wigStartInfo, /// <returns>Returns a work item</returns>
WorkItemCallback callback, public static WorkItem CreateWorkItem(
object state, IWorkItemsGroup workItemsGroup,
WorkItemPriority workItemPriority) WIGStartInfo wigStartInfo,
{ WorkItemCallback callback,
ValidateCallback(callback); object state,
WorkItemPriority workItemPriority)
WorkItemInfo workItemInfo = new WorkItemInfo(); {
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; ValidateCallback(callback);
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback; WorkItemInfo workItemInfo = new WorkItemInfo();
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemInfo.WorkItemPriority = workItemPriority; workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
WorkItem workItem = new WorkItem( workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
workItemsGroup, workItemInfo.WorkItemPriority = workItemPriority;
workItemInfo,
callback, WorkItem workItem = new WorkItem(
state); workItemsGroup,
workItemInfo,
return workItem; callback,
} state);
/// <summary> return workItem;
/// Create a new work item }
/// </summary>
/// <param name="wigStartInfo">Work item group start information</param> /// <summary>
/// <param name="workItemInfo">Work item information</param> /// Create a new work item
/// <param name="callback">A callback to execute</param> /// </summary>
/// <param name="state"> /// <param name="workItemsGroup">The work items group</param>
/// The context object of the work item. Used for passing arguments to the work item. /// <param name="wigStartInfo">Work item group start information</param>
/// </param> /// <param name="workItemInfo">Work item information</param>
/// <returns>Returns a work item</returns> /// <param name="callback">A callback to execute</param>
public static WorkItem CreateWorkItem( /// <param name="state">
IWorkItemsGroup workItemsGroup, /// The context object of the work item. Used for passing arguments to the work item.
WIGStartInfo wigStartInfo, /// </param>
WorkItemInfo workItemInfo, /// <returns>Returns a work item</returns>
WorkItemCallback callback, public static WorkItem CreateWorkItem(
object state) IWorkItemsGroup workItemsGroup,
{ WIGStartInfo wigStartInfo,
ValidateCallback(callback); WorkItemInfo workItemInfo,
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback); WorkItemCallback callback,
object state)
WorkItem workItem = new WorkItem( {
workItemsGroup, ValidateCallback(callback);
new WorkItemInfo(workItemInfo), ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
callback,
state); WorkItem workItem = new WorkItem(
workItemsGroup,
return workItem; new WorkItemInfo(workItemInfo),
} callback,
state);
/// <summary>
/// Create a new work item return workItem;
/// </summary> }
/// <param name="wigStartInfo">Work item group start information</param>
/// <param name="callback">A callback to execute</param> /// <summary>
/// <param name="state"> /// Create a new work item
/// The context object of the work item. Used for passing arguments to the work item. /// </summary>
/// </param> /// <param name="workItemsGroup">The work items group</param>
/// <param name="postExecuteWorkItemCallback"> /// <param name="wigStartInfo">Work item group start information</param>
/// A delegate to call after the callback completion /// <param name="callback">A callback to execute</param>
/// </param> /// <param name="state">
/// <returns>Returns a work item</returns> /// The context object of the work item. Used for passing arguments to the work item.
public static WorkItem CreateWorkItem( /// </param>
IWorkItemsGroup workItemsGroup, /// <param name="postExecuteWorkItemCallback">
WIGStartInfo wigStartInfo, /// A delegate to call after the callback completion
WorkItemCallback callback, /// </param>
object state, /// <returns>Returns a work item</returns>
PostExecuteWorkItemCallback postExecuteWorkItemCallback) public static WorkItem CreateWorkItem(
{ IWorkItemsGroup workItemsGroup,
ValidateCallback(callback); WIGStartInfo wigStartInfo,
ValidateCallback(postExecuteWorkItemCallback); WorkItemCallback callback,
object state,
WorkItemInfo workItemInfo = new WorkItemInfo(); PostExecuteWorkItemCallback postExecuteWorkItemCallback)
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; {
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; ValidateCallback(callback);
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; ValidateCallback(postExecuteWorkItemCallback);
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; WorkItemInfo workItemInfo = new WorkItemInfo();
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
WorkItem workItem = new WorkItem( workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemsGroup, workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
workItemInfo, workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
callback, workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
state); workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
return workItem; WorkItem workItem = new WorkItem(
} workItemsGroup,
workItemInfo,
/// <summary> callback,
/// Create a new work item state);
/// </summary>
/// <param name="wigStartInfo">Work item group start information</param> return workItem;
/// <param name="callback">A callback to execute</param> }
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item. /// <summary>
/// </param> /// Create a new work item
/// <param name="postExecuteWorkItemCallback"> /// </summary>
/// A delegate to call after the callback completion /// <param name="workItemsGroup">The work items group</param>
/// </param> /// <param name="wigStartInfo">Work item group start information</param>
/// <param name="workItemPriority">The work item priority</param> /// <param name="callback">A callback to execute</param>
/// <returns>Returns a work item</returns> /// <param name="state">
public static WorkItem CreateWorkItem( /// The context object of the work item. Used for passing arguments to the work item.
IWorkItemsGroup workItemsGroup, /// </param>
WIGStartInfo wigStartInfo, /// <param name="postExecuteWorkItemCallback">
WorkItemCallback callback, /// A delegate to call after the callback completion
object state, /// </param>
PostExecuteWorkItemCallback postExecuteWorkItemCallback, /// <param name="workItemPriority">The work item priority</param>
WorkItemPriority workItemPriority) /// <returns>Returns a work item</returns>
{ public static WorkItem CreateWorkItem(
ValidateCallback(callback); IWorkItemsGroup workItemsGroup,
ValidateCallback(postExecuteWorkItemCallback); WIGStartInfo wigStartInfo,
WorkItemCallback callback,
WorkItemInfo workItemInfo = new WorkItemInfo(); object state,
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; PostExecuteWorkItemCallback postExecuteWorkItemCallback,
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; WorkItemPriority workItemPriority)
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; {
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; ValidateCallback(callback);
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; ValidateCallback(postExecuteWorkItemCallback);
workItemInfo.WorkItemPriority = workItemPriority;
WorkItemInfo workItemInfo = new WorkItemInfo();
WorkItem workItem = new WorkItem( workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
workItemsGroup, workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemInfo, workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
callback, workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
state); workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
workItemInfo.WorkItemPriority = workItemPriority;
return workItem;
} WorkItem workItem = new WorkItem(
workItemsGroup,
/// <summary> workItemInfo,
/// Create a new work item callback,
/// </summary> state);
/// <param name="wigStartInfo">Work item group start information</param>
/// <param name="callback">A callback to execute</param> return workItem;
/// <param name="state"> }
/// The context object of the work item. Used for passing arguments to the work item.
/// </param> /// <summary>
/// <param name="postExecuteWorkItemCallback"> /// Create a new work item
/// A delegate to call after the callback completion /// </summary>
/// </param> /// <param name="workItemsGroup">The work items group</param>
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> /// <param name="wigStartInfo">Work item group start information</param>
/// <returns>Returns a work item</returns> /// <param name="callback">A callback to execute</param>
public static WorkItem CreateWorkItem( /// <param name="state">
IWorkItemsGroup workItemsGroup, /// The context object of the work item. Used for passing arguments to the work item.
WIGStartInfo wigStartInfo, /// </param>
WorkItemCallback callback, /// <param name="postExecuteWorkItemCallback">
object state, /// A delegate to call after the callback completion
PostExecuteWorkItemCallback postExecuteWorkItemCallback, /// </param>
CallToPostExecute callToPostExecute) /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
{ /// <returns>Returns a work item</returns>
ValidateCallback(callback); public static WorkItem CreateWorkItem(
ValidateCallback(postExecuteWorkItemCallback); IWorkItemsGroup workItemsGroup,
WIGStartInfo wigStartInfo,
WorkItemInfo workItemInfo = new WorkItemInfo(); WorkItemCallback callback,
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; object state,
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; PostExecuteWorkItemCallback postExecuteWorkItemCallback,
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; CallToPostExecute callToPostExecute)
workItemInfo.CallToPostExecute = callToPostExecute; {
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; ValidateCallback(callback);
ValidateCallback(postExecuteWorkItemCallback);
WorkItem workItem = new WorkItem(
workItemsGroup, WorkItemInfo workItemInfo = new WorkItemInfo();
workItemInfo, workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
callback, workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
state); workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
workItemInfo.CallToPostExecute = callToPostExecute;
return workItem; workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
} workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
/// <summary> WorkItem workItem = new WorkItem(
/// Create a new work item workItemsGroup,
/// </summary> workItemInfo,
/// <param name="wigStartInfo">Work item group start information</param> callback,
/// <param name="callback">A callback to execute</param> state);
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item. return workItem;
/// </param> }
/// <param name="postExecuteWorkItemCallback">
/// A delegate to call after the callback completion /// <summary>
/// </param> /// Create a new work item
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> /// </summary>
/// <param name="workItemPriority">The work item priority</param> /// <param name="workItemsGroup">The work items group</param>
/// <returns>Returns a work item</returns> /// <param name="wigStartInfo">Work item group start information</param>
public static WorkItem CreateWorkItem( /// <param name="callback">A callback to execute</param>
IWorkItemsGroup workItemsGroup, /// <param name="state">
WIGStartInfo wigStartInfo, /// The context object of the work item. Used for passing arguments to the work item.
WorkItemCallback callback, /// </param>
object state, /// <param name="postExecuteWorkItemCallback">
PostExecuteWorkItemCallback postExecuteWorkItemCallback, /// A delegate to call after the callback completion
CallToPostExecute callToPostExecute, /// </param>
WorkItemPriority workItemPriority) /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
{ /// <param name="workItemPriority">The work item priority</param>
/// <returns>Returns a work item</returns>
ValidateCallback(callback); public static WorkItem CreateWorkItem(
ValidateCallback(postExecuteWorkItemCallback); IWorkItemsGroup workItemsGroup,
WIGStartInfo wigStartInfo,
WorkItemInfo workItemInfo = new WorkItemInfo(); WorkItemCallback callback,
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; object state,
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; PostExecuteWorkItemCallback postExecuteWorkItemCallback,
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; CallToPostExecute callToPostExecute,
workItemInfo.CallToPostExecute = callToPostExecute; WorkItemPriority workItemPriority)
workItemInfo.WorkItemPriority = workItemPriority; {
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
ValidateCallback(callback);
WorkItem workItem = new WorkItem( ValidateCallback(postExecuteWorkItemCallback);
workItemsGroup,
workItemInfo, WorkItemInfo workItemInfo = new WorkItemInfo();
callback, workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
state); workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
return workItem; workItemInfo.CallToPostExecute = callToPostExecute;
} workItemInfo.WorkItemPriority = workItemPriority;
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
private static void ValidateCallback(Delegate callback)
{ WorkItem workItem = new WorkItem(
if(callback.GetInvocationList().Length > 1) workItemsGroup,
{ workItemInfo,
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains"); callback,
} state);
}
} return workItem;
}
#endregion
} private static void ValidateCallback(Delegate callback)
{
if (callback != null && callback.GetInvocationList().Length > 1)
{
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
}
}
}
#endregion
}

View File

@ -1,102 +1,69 @@
// Ami Bar namespace Amib.Threading
// amibar@gmail.com {
#region WorkItemInfo class
namespace Amib.Threading
{ /// <summary>
#region WorkItemInfo class /// Summary description for WorkItemInfo.
/// </summary>
/// <summary> public class WorkItemInfo
/// Summary description for WorkItemInfo. {
/// </summary> public WorkItemInfo()
public class WorkItemInfo {
{ UseCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
/// <summary> UseCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
/// Use the caller's security context DisposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
/// </summary> CallToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
private bool _useCallerCallContext; PostExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
WorkItemPriority = SmartThreadPool.DefaultWorkItemPriority;
/// <summary> }
/// Use the caller's security context
/// </summary> public WorkItemInfo(WorkItemInfo workItemInfo)
private bool _useCallerHttpContext; {
UseCallerCallContext = workItemInfo.UseCallerCallContext;
/// <summary> UseCallerHttpContext = workItemInfo.UseCallerHttpContext;
/// Dispose of the state object of a work item DisposeOfStateObjects = workItemInfo.DisposeOfStateObjects;
/// </summary> CallToPostExecute = workItemInfo.CallToPostExecute;
private bool _disposeOfStateObjects; PostExecuteWorkItemCallback = workItemInfo.PostExecuteWorkItemCallback;
WorkItemPriority = workItemInfo.WorkItemPriority;
/// <summary> Timeout = workItemInfo.Timeout;
/// The option to run the post execute }
/// </summary>
private CallToPostExecute _callToPostExecute; /// <summary>
/// Get/Set if to use the caller's security context
/// <summary> /// </summary>
/// A post execute callback to call when none is provided in public bool UseCallerCallContext { get; set; }
/// the QueueWorkItem method.
/// </summary> /// <summary>
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback; /// Get/Set if to use the caller's HTTP context
/// </summary>
/// <summary> public bool UseCallerHttpContext { get; set; }
/// The priority of the work item
/// </summary> /// <summary>
private WorkItemPriority _workItemPriority; /// Get/Set if to dispose of the state object of a work item
/// </summary>
public WorkItemInfo() public bool DisposeOfStateObjects { get; set; }
{
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext; /// <summary>
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext; /// Get/Set the run the post execute options
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects; /// </summary>
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute; public CallToPostExecute CallToPostExecute { get; set; }
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority; /// <summary>
} /// Get/Set the post execute callback
/// </summary>
public WorkItemInfo(WorkItemInfo workItemInfo) public PostExecuteWorkItemCallback PostExecuteWorkItemCallback { get; set; }
{
_useCallerCallContext = workItemInfo._useCallerCallContext; /// <summary>
_useCallerHttpContext = workItemInfo._useCallerHttpContext; /// Get/Set the work item's priority
_disposeOfStateObjects = workItemInfo._disposeOfStateObjects; /// </summary>
_callToPostExecute = workItemInfo._callToPostExecute; public WorkItemPriority WorkItemPriority { get; set; }
_postExecuteWorkItemCallback = workItemInfo._postExecuteWorkItemCallback;
_workItemPriority = workItemInfo._workItemPriority; /// <summary>
} /// Get/Set the work item's timout in milliseconds.
/// This is a passive timout. When the timout expires the work item won't be actively aborted!
public bool UseCallerCallContext /// </summary>
{ public long Timeout { get; set; }
get { return _useCallerCallContext; } }
set { _useCallerCallContext = value; }
} #endregion
}
public bool UseCallerHttpContext
{
get { return _useCallerHttpContext; }
set { _useCallerHttpContext = value; }
}
public bool DisposeOfStateObjects
{
get { return _disposeOfStateObjects; }
set { _disposeOfStateObjects = value; }
}
public CallToPostExecute CallToPostExecute
{
get { return _callToPostExecute; }
set { _callToPostExecute = value; }
}
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
{
get { return _postExecuteWorkItemCallback; }
set { _postExecuteWorkItemCallback = value; }
}
public WorkItemPriority WorkItemPriority
{
get { return _workItemPriority; }
set { _workItemPriority = value; }
}
}
#endregion
}

View File

@ -0,0 +1,128 @@
using System;
using System.Threading;
namespace Amib.Threading.Internal
{
#region WorkItemResultTWrapper class
internal class WorkItemResultTWrapper<TResult> : IWorkItemResult<TResult>, IInternalWaitableResult
{
private readonly IWorkItemResult _workItemResult;
public WorkItemResultTWrapper(IWorkItemResult workItemResult)
{
_workItemResult = workItemResult;
}
#region IWorkItemResult<TResult> Members
public TResult GetResult()
{
return (TResult)_workItemResult.GetResult();
}
public TResult GetResult(int millisecondsTimeout, bool exitContext)
{
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext);
}
public TResult GetResult(TimeSpan timeout, bool exitContext)
{
return (TResult)_workItemResult.GetResult(timeout, exitContext);
}
public TResult GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
}
public TResult GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
{
return (TResult)_workItemResult.GetResult(timeout, exitContext, cancelWaitHandle);
}
public TResult GetResult(out Exception e)
{
return (TResult)_workItemResult.GetResult(out e);
}
public TResult GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
{
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, out e);
}
public TResult GetResult(TimeSpan timeout, bool exitContext, out Exception e)
{
return (TResult)_workItemResult.GetResult(timeout, exitContext, out e);
}
public TResult GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return (TResult)_workItemResult.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
}
public TResult GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
{
return (TResult)_workItemResult.GetResult(timeout, exitContext, cancelWaitHandle, out e);
}
public bool IsCompleted
{
get { return _workItemResult.IsCompleted; }
}
public bool IsCanceled
{
get { return _workItemResult.IsCanceled; }
}
public object State
{
get { return _workItemResult.State; }
}
public bool Cancel()
{
return _workItemResult.Cancel();
}
public bool Cancel(bool abortExecution)
{
return _workItemResult.Cancel(abortExecution);
}
public WorkItemPriority WorkItemPriority
{
get { return _workItemResult.WorkItemPriority; }
}
public TResult Result
{
get { return (TResult)_workItemResult.Result; }
}
public object Exception
{
get { return (TResult)_workItemResult.Exception; }
}
#region IInternalWorkItemResult Members
public IWorkItemResult GetWorkItemResult()
{
return _workItemResult.GetWorkItemResult();
}
public IWorkItemResult<TRes> GetWorkItemResultT<TRes>()
{
return (IWorkItemResult<TRes>)this;
}
#endregion
#endregion
}
#endregion
}

View File

@ -1,512 +1,361 @@
// Ami Bar using System;
// amibar@gmail.com using System.Threading;
using System.Runtime.CompilerServices;
using System; using System.Diagnostics;
using System.Threading;
using System.Runtime.CompilerServices; namespace Amib.Threading.Internal
using System.Diagnostics; {
namespace Amib.Threading.Internal #region WorkItemsGroup class
{
#region WorkItemsGroup class /// <summary>
/// Summary description for WorkItemsGroup.
/// <summary> /// </summary>
/// Summary description for WorkItemsGroup. public class WorkItemsGroup : WorkItemsGroupBase
/// </summary> {
public class WorkItemsGroup : IWorkItemsGroup #region Private members
{
#region Private members private readonly object _lock = new object();
private object _lock = new object(); /// <summary>
/// <summary> /// A reference to the SmartThreadPool instance that created this
/// Contains the name of this instance of SmartThreadPool. /// WorkItemsGroup.
/// Can be changed by the user. /// </summary>
/// </summary> private readonly SmartThreadPool _stp;
private string _name = "WorkItemsGroup";
/// <summary>
/// <summary> /// The OnIdle event
/// A reference to the SmartThreadPool instance that created this /// </summary>
/// WorkItemsGroup. private event WorkItemsGroupIdleHandler _onIdle;
/// </summary>
private SmartThreadPool _stp; /// <summary>
/// A flag to indicate if the Work Items Group is now suspended.
/// <summary> /// </summary>
/// The OnIdle event private bool _isSuspended;
/// </summary>
private event WorkItemsGroupIdleHandler _onIdle; /// <summary>
/// Defines how many work items of this WorkItemsGroup can run at once.
/// <summary> /// </summary>
/// Defines how many work items of this WorkItemsGroup can run at once. private int _concurrency;
/// </summary>
private int _concurrency; /// <summary>
/// Priority queue to hold work items before they are passed
/// <summary> /// to the SmartThreadPool.
/// Priority queue to hold work items before they are passed /// </summary>
/// to the SmartThreadPool. private readonly PriorityQueue _workItemsQueue;
/// </summary>
private PriorityQueue _workItemsQueue; /// <summary>
/// Indicate how many work items are waiting in the SmartThreadPool
/// <summary> /// queue.
/// Indicate how many work items are waiting in the SmartThreadPool /// This value is used to apply the concurrency.
/// queue. /// </summary>
/// This value is used to apply the concurrency. private int _workItemsInStpQueue;
/// </summary>
private int _workItemsInStpQueue; /// <summary>
/// Indicate how many work items are currently running in the SmartThreadPool.
/// <summary> /// This value is used with the Cancel, to calculate if we can send new
/// Indicate how many work items are currently running in the SmartThreadPool. /// work items to the STP.
/// This value is used with the Cancel, to calculate if we can send new /// </summary>
/// work items to the STP. private int _workItemsExecutingInStp = 0;
/// </summary>
private int _workItemsExecutingInStp = 0; /// <summary>
/// WorkItemsGroup start information
/// <summary> /// </summary>
/// WorkItemsGroup start information private readonly WIGStartInfo _workItemsGroupStartInfo;
/// </summary>
private WIGStartInfo _workItemsGroupStartInfo; /// <summary>
/// Signaled when all of the WorkItemsGroup's work item completed.
/// <summary> /// </summary>
/// Signaled when all of the WorkItemsGroup's work item completed. //private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
/// </summary> private readonly ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true);
private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
/// <summary>
/// <summary> /// A common object for all the work items that this work items group
/// A common object for all the work items that this work items group /// generate so we can mark them to cancel in O(1)
/// generate so we can mark them to cancel in O(1) /// </summary>
/// </summary> private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
#endregion
#endregion
#region Construction
#region Construction
public WorkItemsGroup(
public WorkItemsGroup( SmartThreadPool stp,
SmartThreadPool stp, int concurrency,
int concurrency, WIGStartInfo wigStartInfo)
WIGStartInfo wigStartInfo) {
{ if (concurrency <= 0)
if (concurrency <= 0) {
{ throw new ArgumentOutOfRangeException(
throw new ArgumentOutOfRangeException("concurrency", concurrency, "concurrency must be greater than zero"); "concurrency",
} #if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
_stp = stp; concurrency,
_concurrency = concurrency; #endif
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo); "concurrency must be greater than zero");
_workItemsQueue = new PriorityQueue(); }
_stp = stp;
// The _workItemsInStpQueue gets the number of currently executing work items, _concurrency = concurrency;
// because once a work item is executing, it cannot be cancelled. _workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo).AsReadOnly();
_workItemsInStpQueue = _workItemsExecutingInStp; _workItemsQueue = new PriorityQueue();
} Name = "WorkItemsGroup";
#endregion // The _workItemsInStpQueue gets the number of currently executing work items,
// because once a work item is executing, it cannot be cancelled.
#region IWorkItemsGroup implementation _workItemsInStpQueue = _workItemsExecutingInStp;
/// <summary> _isSuspended = _workItemsGroupStartInfo.StartSuspended;
/// Get/Set the name of the SmartThreadPool instance }
/// </summary>
public string Name #endregion
{
get #region WorkItemsGroupBase Overrides
{
return _name; public override int Concurrency
} {
get { return _concurrency; }
set set
{ {
_name = value; Debug.Assert(value > 0);
}
} int diff = value - _concurrency;
_concurrency = value;
/// <summary> if (diff > 0)
/// Queue a work item {
/// </summary> EnqueueToSTPNextNWorkItem(diff);
/// <param name="callback">A callback to execute</param> }
/// <returns>Returns a work item result</returns> }
public IWorkItemResult QueueWorkItem(WorkItemCallback callback) }
{
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback); public override int WaitingCallbacks
EnqueueToSTPNextWorkItem(workItem); {
return workItem.GetWorkItemResult(); get { return _workItemsQueue.Count; }
} }
/// <summary> public override object[] GetStates()
/// Queue a work item {
/// </summary> lock (_lock)
/// <param name="callback">A callback to execute</param> {
/// <param name="workItemPriority">The priority of the work item</param> object[] states = new object[_workItemsQueue.Count];
/// <returns>Returns a work item result</returns> int i = 0;
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority) foreach (WorkItem workItem in _workItemsQueue)
{ {
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, workItemPriority); states[i] = workItem.GetWorkItemResult().State;
EnqueueToSTPNextWorkItem(workItem); ++i;
return workItem.GetWorkItemResult(); }
} return states;
}
/// <summary> }
/// Queue a work item
/// </summary> /// <summary>
/// <param name="workItemInfo">Work item info</param> /// WorkItemsGroup start information
/// <param name="callback">A callback to execute</param> /// </summary>
/// <returns>Returns a work item result</returns> public override WIGStartInfo WIGStartInfo
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback) {
{ get { return _workItemsGroupStartInfo; }
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback); }
EnqueueToSTPNextWorkItem(workItem);
return workItem.GetWorkItemResult(); /// <summary>
} /// Start the Work Items Group if it was started suspended
/// </summary>
/// <summary> public override void Start()
/// Queue a work item {
/// </summary> // If the Work Items Group already started then quit
/// <param name="callback">A callback to execute</param> if (!_isSuspended)
/// <param name="state"> {
/// The context object of the work item. Used for passing arguments to the work item. return;
/// </param> }
/// <returns>Returns a work item result</returns> _isSuspended = false;
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
{ EnqueueToSTPNextNWorkItem(Math.Min(_workItemsQueue.Count, _concurrency));
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state); }
EnqueueToSTPNextWorkItem(workItem);
return workItem.GetWorkItemResult(); public override void Cancel(bool abortExecution)
} {
lock (_lock)
/// <summary> {
/// Queue a work item _canceledWorkItemsGroup.IsCanceled = true;
/// </summary> _workItemsQueue.Clear();
/// <param name="callback">A callback to execute</param> _workItemsInStpQueue = 0;
/// <param name="state"> _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
/// The context object of the work item. Used for passing arguments to the work item. }
/// </param>
/// <param name="workItemPriority">The work item priority</param> if (abortExecution)
/// <returns>Returns a work item result</returns> {
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority) _stp.CancelAbortWorkItemsGroup(this);
{ }
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, workItemPriority); }
EnqueueToSTPNextWorkItem(workItem);
return workItem.GetWorkItemResult(); /// <summary>
} /// Wait for the thread pool to be idle
/// </summary>
/// <summary> public override bool WaitForIdle(int millisecondsTimeout)
/// Queue a work item {
/// </summary> SmartThreadPool.ValidateWorkItemsGroupWaitForIdle(this);
/// <param name="workItemInfo">Work item information</param> return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false);
/// <param name="callback">A callback to execute</param> }
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item. public override event WorkItemsGroupIdleHandler OnIdle
/// </param> {
/// <returns>Returns a work item result</returns> add { _onIdle += value; }
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state) remove { _onIdle -= value; }
{ }
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback, state);
EnqueueToSTPNextWorkItem(workItem); #endregion
return workItem.GetWorkItemResult();
} #region Private methods
/// <summary> private void RegisterToWorkItemCompletion(IWorkItemResult wir)
/// Queue a work item {
/// </summary> IInternalWorkItemResult iwir = (IInternalWorkItemResult)wir;
/// <param name="callback">A callback to execute</param> iwir.OnWorkItemStarted += OnWorkItemStartedCallback;
/// <param name="state"> iwir.OnWorkItemCompleted += OnWorkItemCompletedCallback;
/// The context object of the work item. Used for passing arguments to the work item. }
/// </param>
/// <param name="postExecuteWorkItemCallback"> public void OnSTPIsStarting()
/// A delegate to call after the callback completion {
/// </param> if (_isSuspended)
/// <returns>Returns a work item result</returns> {
public IWorkItemResult QueueWorkItem( return;
WorkItemCallback callback, }
object state,
PostExecuteWorkItemCallback postExecuteWorkItemCallback) EnqueueToSTPNextNWorkItem(_concurrency);
{ }
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback);
EnqueueToSTPNextWorkItem(workItem); public void EnqueueToSTPNextNWorkItem(int count)
return workItem.GetWorkItemResult(); {
} for (int i = 0; i < count; ++i)
{
/// <summary> EnqueueToSTPNextWorkItem(null, false);
/// Queue a work item }
/// </summary> }
/// <param name="callback">A callback to execute</param>
/// <param name="state"> private object FireOnIdle(object state)
/// The context object of the work item. Used for passing arguments to the work item. {
/// </param> FireOnIdleImpl(_onIdle);
/// <param name="postExecuteWorkItemCallback"> return null;
/// A delegate to call after the callback completion }
/// </param>
/// <param name="workItemPriority">The work item priority</param> [MethodImpl(MethodImplOptions.NoInlining)]
/// <returns>Returns a work item result</returns> private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
public IWorkItemResult QueueWorkItem( {
WorkItemCallback callback, if(null == onIdle)
object state, {
PostExecuteWorkItemCallback postExecuteWorkItemCallback, return;
WorkItemPriority workItemPriority) }
{
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority); Delegate[] delegates = onIdle.GetInvocationList();
EnqueueToSTPNextWorkItem(workItem); foreach(WorkItemsGroupIdleHandler eh in delegates)
return workItem.GetWorkItemResult(); {
} try
{
/// <summary> eh(this);
/// Queue a work item }
/// </summary> catch { } // Suppress exceptions
/// <param name="callback">A callback to execute</param> }
/// <param name="state"> }
/// The context object of the work item. Used for passing arguments to the work item.
/// </param> private void OnWorkItemStartedCallback(WorkItem workItem)
/// <param name="postExecuteWorkItemCallback"> {
/// A delegate to call after the callback completion lock(_lock)
/// </param> {
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> ++_workItemsExecutingInStp;
/// <returns>Returns a work item result</returns> }
public IWorkItemResult QueueWorkItem( }
WorkItemCallback callback,
object state, private void OnWorkItemCompletedCallback(WorkItem workItem)
PostExecuteWorkItemCallback postExecuteWorkItemCallback, {
CallToPostExecute callToPostExecute) EnqueueToSTPNextWorkItem(null, true);
{ }
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
EnqueueToSTPNextWorkItem(workItem); internal override void Enqueue(WorkItem workItem)
return workItem.GetWorkItemResult(); {
} EnqueueToSTPNextWorkItem(workItem);
}
/// <summary>
/// Queue a work item private void EnqueueToSTPNextWorkItem(WorkItem workItem)
/// </summary> {
/// <param name="callback">A callback to execute</param> EnqueueToSTPNextWorkItem(workItem, false);
/// <param name="state"> }
/// The context object of the work item. Used for passing arguments to the work item.
/// </param> private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
/// <param name="postExecuteWorkItemCallback"> {
/// A delegate to call after the callback completion lock(_lock)
/// </param> {
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> // Got here from OnWorkItemCompletedCallback()
/// <param name="workItemPriority">The work item priority</param> if (decrementWorkItemsInStpQueue)
/// <returns>Returns a work item result</returns> {
public IWorkItemResult QueueWorkItem( --_workItemsInStpQueue;
WorkItemCallback callback,
object state, if(_workItemsInStpQueue < 0)
PostExecuteWorkItemCallback postExecuteWorkItemCallback, {
CallToPostExecute callToPostExecute, _workItemsInStpQueue = 0;
WorkItemPriority workItemPriority) }
{
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority); --_workItemsExecutingInStp;
EnqueueToSTPNextWorkItem(workItem);
return workItem.GetWorkItemResult(); if(_workItemsExecutingInStp < 0)
} {
_workItemsExecutingInStp = 0;
/// <summary> }
/// Wait for the thread pool to be idle }
/// </summary>
public void WaitForIdle() // If the work item is not null then enqueue it
{ if (null != workItem)
WaitForIdle(Timeout.Infinite); {
} workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
/// <summary> RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
/// Wait for the thread pool to be idle _workItemsQueue.Enqueue(workItem);
/// </summary> //_stp.IncrementWorkItemsCount();
public bool WaitForIdle(TimeSpan timeout)
{ if ((1 == _workItemsQueue.Count) &&
return WaitForIdle((int)timeout.TotalMilliseconds); (0 == _workItemsInStpQueue))
} {
_stp.RegisterWorkItemsGroup(this);
/// <summary> IsIdle = false;
/// Wait for the thread pool to be idle _isIdleWaitHandle.Reset();
/// </summary> }
public bool WaitForIdle(int millisecondsTimeout) }
{
_stp.ValidateWorkItemsGroupWaitForIdle(this); // If the work items queue of the group is empty than quit
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false); if (0 == _workItemsQueue.Count)
} {
if (0 == _workItemsInStpQueue)
public int WaitingCallbacks {
{ _stp.UnregisterWorkItemsGroup(this);
get IsIdle = true;
{ _isIdleWaitHandle.Set();
return _workItemsQueue.Count; if (decrementWorkItemsInStpQueue && _onIdle != null && _onIdle.GetInvocationList().Length > 0)
} {
} _stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
}
public event WorkItemsGroupIdleHandler OnIdle }
{ return;
add }
{
_onIdle += value; if (!_isSuspended)
} {
remove if (_workItemsInStpQueue < _concurrency)
{ {
_onIdle -= value; WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
} try
} {
_stp.Enqueue(nextWorkItem);
public void Cancel() }
{ catch (ObjectDisposedException e)
lock(_lock) {
{ e.GetHashCode();
_canceledWorkItemsGroup.IsCanceled = true; // The STP has been shutdown
_workItemsQueue.Clear(); }
_workItemsInStpQueue = 0;
_canceledWorkItemsGroup = new CanceledWorkItemsGroup(); ++_workItemsInStpQueue;
} }
} }
}
public void Start() }
{
lock (this) #endregion
{ }
if (!_workItemsGroupStartInfo.StartSuspended)
{ #endregion
return; }
}
_workItemsGroupStartInfo.StartSuspended = false;
}
for(int i = 0; i < _concurrency; ++i)
{
EnqueueToSTPNextWorkItem(null, false);
}
}
#endregion
#region Private methods
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
{
IInternalWorkItemResult iwir = wir as IInternalWorkItemResult;
iwir.OnWorkItemStarted += new WorkItemStateCallback(OnWorkItemStartedCallback);
iwir.OnWorkItemCompleted += new WorkItemStateCallback(OnWorkItemCompletedCallback);
}
public void OnSTPIsStarting()
{
lock (this)
{
if (_workItemsGroupStartInfo.StartSuspended)
{
return;
}
}
for(int i = 0; i < _concurrency; ++i)
{
EnqueueToSTPNextWorkItem(null, false);
}
}
private object FireOnIdle(object state)
{
FireOnIdleImpl(_onIdle);
return null;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
{
if(null == onIdle)
{
return;
}
Delegate[] delegates = onIdle.GetInvocationList();
foreach(WorkItemsGroupIdleHandler eh in delegates)
{
try
{
eh(this);
}
// Ignore exceptions
catch{}
}
}
private void OnWorkItemStartedCallback(WorkItem workItem)
{
lock(_lock)
{
++_workItemsExecutingInStp;
}
}
private void OnWorkItemCompletedCallback(WorkItem workItem)
{
EnqueueToSTPNextWorkItem(null, true);
}
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
{
EnqueueToSTPNextWorkItem(workItem, false);
}
private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
{
lock(_lock)
{
// Got here from OnWorkItemCompletedCallback()
if (decrementWorkItemsInStpQueue)
{
--_workItemsInStpQueue;
if(_workItemsInStpQueue < 0)
{
_workItemsInStpQueue = 0;
}
--_workItemsExecutingInStp;
if(_workItemsExecutingInStp < 0)
{
_workItemsExecutingInStp = 0;
}
}
// If the work item is not null then enqueue it
if (null != workItem)
{
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
_workItemsQueue.Enqueue(workItem);
//_stp.IncrementWorkItemsCount();
if ((1 == _workItemsQueue.Count) &&
(0 == _workItemsInStpQueue))
{
_stp.RegisterWorkItemsGroup(this);
Trace.WriteLine("WorkItemsGroup " + Name + " is NOT idle");
_isIdleWaitHandle.Reset();
}
}
// If the work items queue of the group is empty than quit
if (0 == _workItemsQueue.Count)
{
if (0 == _workItemsInStpQueue)
{
_stp.UnregisterWorkItemsGroup(this);
Trace.WriteLine("WorkItemsGroup " + Name + " is idle");
_isIdleWaitHandle.Set();
_stp.QueueWorkItem(new WorkItemCallback(this.FireOnIdle));
}
return;
}
if (!_workItemsGroupStartInfo.StartSuspended)
{
if (_workItemsInStpQueue < _concurrency)
{
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
_stp.Enqueue(nextWorkItem, true);
++_workItemsInStpQueue;
}
}
}
}
#endregion
}
#endregion
}

View File

@ -0,0 +1,471 @@
using System;
using System.Threading;
namespace Amib.Threading.Internal
{
public abstract class WorkItemsGroupBase : IWorkItemsGroup
{
#region Private Fields
/// <summary>
/// Contains the name of this instance of SmartThreadPool.
/// Can be changed by the user.
/// </summary>
private string _name = "WorkItemsGroupBase";
public WorkItemsGroupBase()
{
IsIdle = true;
}
#endregion
#region IWorkItemsGroup Members
#region Public Methods
/// <summary>
/// Get/Set the name of the SmartThreadPool/WorkItemsGroup instance
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
#endregion
#region Abstract Methods
public abstract int Concurrency { get; set; }
public abstract int WaitingCallbacks { get; }
public abstract object[] GetStates();
public abstract WIGStartInfo WIGStartInfo { get; }
public abstract void Start();
public abstract void Cancel(bool abortExecution);
public abstract bool WaitForIdle(int millisecondsTimeout);
public abstract event WorkItemsGroupIdleHandler OnIdle;
internal abstract void Enqueue(WorkItem workItem);
internal virtual void PreQueueWorkItem() { }
#endregion
#region Common Base Methods
/// <summary>
/// Cancel all the work items.
/// Same as Cancel(false)
/// </summary>
public virtual void Cancel()
{
Cancel(false);
}
/// <summary>
/// Wait for the SmartThreadPool/WorkItemsGroup to be idle
/// </summary>
public void WaitForIdle()
{
WaitForIdle(Timeout.Infinite);
}
/// <summary>
/// Wait for the SmartThreadPool/WorkItemsGroup to be idle
/// </summary>
public bool WaitForIdle(TimeSpan timeout)
{
return WaitForIdle((int)timeout.TotalMilliseconds);
}
/// <summary>
/// IsIdle is true when there are no work items running or queued.
/// </summary>
public bool IsIdle { get; protected set; }
#endregion
#region QueueWorkItem
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
{
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="workItemPriority">The priority of the work item</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, workItemPriority);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="workItemInfo">Work item info</param>
/// <param name="callback">A callback to execute</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, workItemInfo, callback);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
{
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <param name="workItemPriority">The work item priority</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, workItemPriority);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="workItemInfo">Work item information</param>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, workItemInfo, callback, state);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <param name="postExecuteWorkItemCallback">
/// A delegate to call after the callback completion
/// </param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(
WorkItemCallback callback,
object state,
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <param name="postExecuteWorkItemCallback">
/// A delegate to call after the callback completion
/// </param>
/// <param name="workItemPriority">The work item priority</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(
WorkItemCallback callback,
object state,
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
WorkItemPriority workItemPriority)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <param name="postExecuteWorkItemCallback">
/// A delegate to call after the callback completion
/// </param>
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(
WorkItemCallback callback,
object state,
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
CallToPostExecute callToPostExecute)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
/// <summary>
/// Queue a work item
/// </summary>
/// <param name="callback">A callback to execute</param>
/// <param name="state">
/// The context object of the work item. Used for passing arguments to the work item.
/// </param>
/// <param name="postExecuteWorkItemCallback">
/// A delegate to call after the callback completion
/// </param>
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
/// <param name="workItemPriority">The work item priority</param>
/// <returns>Returns a work item result</returns>
public IWorkItemResult QueueWorkItem(
WorkItemCallback callback,
object state,
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
CallToPostExecute callToPostExecute,
WorkItemPriority workItemPriority)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, WIGStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
Enqueue(workItem);
return workItem.GetWorkItemResult();
}
#endregion
#region QueueWorkItem(Action<...>)
public IWorkItemResult QueueWorkItem(Action action)
{
return QueueWorkItem (action, SmartThreadPool.DefaultWorkItemPriority);
}
public IWorkItemResult QueueWorkItem (Action action, WorkItemPriority priority)
{
PreQueueWorkItem ();
WorkItem workItem = WorkItemFactory.CreateWorkItem (
this,
WIGStartInfo,
delegate
{
action.Invoke ();
return null;
}, priority);
Enqueue (workItem);
return workItem.GetWorkItemResult ();
}
public IWorkItemResult QueueWorkItem<T>(Action<T> action, T arg)
{
return QueueWorkItem<T> (action, arg, SmartThreadPool.DefaultWorkItemPriority);
}
public IWorkItemResult QueueWorkItem<T> (Action<T> action, T arg, WorkItemPriority priority)
{
PreQueueWorkItem ();
WorkItem workItem = WorkItemFactory.CreateWorkItem (
this,
WIGStartInfo,
state =>
{
action.Invoke (arg);
return null;
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null, priority);
Enqueue (workItem);
return workItem.GetWorkItemResult ();
}
public IWorkItemResult QueueWorkItem<T1, T2>(Action<T1, T2> action, T1 arg1, T2 arg2)
{
return QueueWorkItem<T1, T2> (action, arg1, arg2, SmartThreadPool.DefaultWorkItemPriority);
}
public IWorkItemResult QueueWorkItem<T1, T2> (Action<T1, T2> action, T1 arg1, T2 arg2, WorkItemPriority priority)
{
PreQueueWorkItem ();
WorkItem workItem = WorkItemFactory.CreateWorkItem (
this,
WIGStartInfo,
state =>
{
action.Invoke (arg1, arg2);
return null;
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null, priority);
Enqueue (workItem);
return workItem.GetWorkItemResult ();
}
public IWorkItemResult QueueWorkItem<T1, T2, T3>(Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3)
{
return QueueWorkItem<T1, T2, T3> (action, arg1, arg2, arg3, SmartThreadPool.DefaultWorkItemPriority);
;
}
public IWorkItemResult QueueWorkItem<T1, T2, T3> (Action<T1, T2, T3> action, T1 arg1, T2 arg2, T3 arg3, WorkItemPriority priority)
{
PreQueueWorkItem ();
WorkItem workItem = WorkItemFactory.CreateWorkItem (
this,
WIGStartInfo,
state =>
{
action.Invoke (arg1, arg2, arg3);
return null;
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null, priority);
Enqueue (workItem);
return workItem.GetWorkItemResult ();
}
public IWorkItemResult QueueWorkItem<T1, T2, T3, T4>(
Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
return QueueWorkItem<T1, T2, T3, T4> (action, arg1, arg2, arg3, arg4,
SmartThreadPool.DefaultWorkItemPriority);
}
public IWorkItemResult QueueWorkItem<T1, T2, T3, T4> (
Action<T1, T2, T3, T4> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, WorkItemPriority priority)
{
PreQueueWorkItem ();
WorkItem workItem = WorkItemFactory.CreateWorkItem (
this,
WIGStartInfo,
state =>
{
action.Invoke (arg1, arg2, arg3, arg4);
return null;
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null, priority);
Enqueue (workItem);
return workItem.GetWorkItemResult ();
}
#endregion
#region QueueWorkItem(Func<...>)
public IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
state =>
{
return func.Invoke();
});
Enqueue(workItem);
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
}
public IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
state =>
{
return func.Invoke(arg);
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg } : null);
Enqueue(workItem);
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
}
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
state =>
{
return func.Invoke(arg1, arg2);
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2 } : null);
Enqueue(workItem);
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
}
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(
Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
state =>
{
return func.Invoke(arg1, arg2, arg3);
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3 } : null);
Enqueue(workItem);
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
}
public IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(
Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
PreQueueWorkItem();
WorkItem workItem = WorkItemFactory.CreateWorkItem(
this,
WIGStartInfo,
state =>
{
return func.Invoke(arg1, arg2, arg3, arg4);
},
WIGStartInfo.FillStateWithArgs ? new object[] { arg1, arg2, arg3, arg4 } : null);
Enqueue(workItem);
return new WorkItemResultTWrapper<TResult>(workItem.GetWorkItemResult());
}
#endregion
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@ -21,18 +21,21 @@
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>] ; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
; * ; *
[Startup] [Startup]
; Place to create a PID file
; If no path if specified then a PID file is not created.
; PIDFile = "/tmp/my.pid"
; Plugin Registry Location ; Plugin Registry Location
; Set path to directory for plugin registry. Information ; Set path to directory for plugin registry. Information
; about the registered repositories and installed plugins ; about the registered repositories and installed plugins
; will be stored here ; will be stored here
; The Robust.exe process must have R/W access to the location ; The Robust.exe process must have R/W access to the location
RegistryLocation = "." RegistryLocation = "."
; Modular configurations ; Modular configurations
; Set path to directory for modular ini files... ; Set path to directory for modular ini files...
; The Robust.exe process must have R/W access to the location ; The Robust.exe process must have R/W access to the location
ConfigDirectory = "/home/opensim/etc/Configs" ConfigDirectory = "/home/opensim/etc/Configs"
[ServiceList] [ServiceList]

View File

@ -13,19 +13,21 @@
; * [[<ConfigName>@]<port>/]<dll name>[:<class name>] ; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
; * ; *
[Startup] [Startup]
; Place to create a PID file
; If no path if specified then a PID file is not created.
; PIDFile = "/tmp/my.pid"
; Plugin Registry Location ; Plugin Registry Location
; Set path to directory for plugin registry. Information ; Set path to directory for plugin registry. Information
; about the registered repositories and installed plugins ; about the registered repositories and installed plugins
; will be stored here ; will be stored here
; The Robust.exe process must have R/W access to the location ; The Robust.exe process must have R/W access to the location
RegistryLocation = "." RegistryLocation = "."
; Modular configurations
; Modular configurations ; Set path to directory for modular ini files...
; Set path to directory for modular ini files... ; The Robust.exe process must have R/W access to the location
; The Robust.exe process must have R/W access to the location ConfigDirectory = "/home/opensim/etc/Configs"
ConfigDirectory = "/home/opensim/etc/Configs"
[ServiceList] [ServiceList]
AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector" AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"