aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty
diff options
context:
space:
mode:
Diffstat (limited to 'ThirdParty')
-rw-r--r--ThirdParty/SmartThreadPool/CallerThreadContext.cs198
-rw-r--r--ThirdParty/SmartThreadPool/EventWaitHandle.cs30
-rw-r--r--ThirdParty/SmartThreadPool/EventWaitHandleFactory.cs6
-rw-r--r--ThirdParty/SmartThreadPool/Interfaces.cs444
-rw-r--r--ThirdParty/SmartThreadPool/InternalInterfaces.cs2
-rw-r--r--ThirdParty/SmartThreadPool/PriorityQueue.cs446
-rw-r--r--ThirdParty/SmartThreadPool/STPPerformanceCounter.cs606
-rw-r--r--ThirdParty/SmartThreadPool/STPStartInfo.cs150
-rw-r--r--ThirdParty/SmartThreadPool/SmartThreadPool.ThreadEntry.cs6
-rw-r--r--ThirdParty/SmartThreadPool/SmartThreadPool.cs1643
-rw-r--r--ThirdParty/SmartThreadPool/WIGStartInfo.cs218
-rw-r--r--ThirdParty/SmartThreadPool/WorkItem.cs20
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemFactory.cs592
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemInfo.cs104
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemsGroup.cs452
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemsGroupBase.cs14
-rw-r--r--ThirdParty/SmartThreadPool/WorkItemsQueue.cs871
17 files changed, 2904 insertions, 2898 deletions
diff --git a/ThirdParty/SmartThreadPool/CallerThreadContext.cs b/ThirdParty/SmartThreadPool/CallerThreadContext.cs
index e63add5..925c39b 100644
--- a/ThirdParty/SmartThreadPool/CallerThreadContext.cs
+++ b/ThirdParty/SmartThreadPool/CallerThreadContext.cs
@@ -13,125 +13,125 @@ namespace Amib.Threading.Internal
13{ 13{
14#region CallerThreadContext class 14#region CallerThreadContext class
15 15
16 /// <summary> 16 /// <summary>
17 /// This class stores the caller call context in order to restore 17 /// This class stores the caller call context in order to restore
18 /// it when the work item is executed in the thread pool environment. 18 /// it when the work item is executed in the thread pool environment.
19 /// </summary> 19 /// </summary>
20 internal class CallerThreadContext 20 internal class CallerThreadContext
21 { 21 {
22#region Prepare reflection information 22#region Prepare reflection information
23 23
24 // Cached type information. 24 // Cached type information.
25 private static readonly MethodInfo getLogicalCallContextMethodInfo = 25 private static readonly MethodInfo getLogicalCallContextMethodInfo =
26 typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); 26 typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
27 27
28 private static readonly MethodInfo setLogicalCallContextMethodInfo = 28 private static readonly MethodInfo setLogicalCallContextMethodInfo =
29 typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); 29 typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
30 30
31 private static string HttpContextSlotName = GetHttpContextSlotName(); 31 private static string HttpContextSlotName = GetHttpContextSlotName();
32 32
33 private static string GetHttpContextSlotName() 33 private static string GetHttpContextSlotName()
34 { 34 {
35 FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); 35 FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
36 36
37 if (fi != null) 37 if (fi != null)
38 { 38 {
39 return (string) fi.GetValue(null); 39 return (string) fi.GetValue(null);
40 } 40 }
41 41
42 return "HttpContext"; 42 return "HttpContext";
43 } 43 }
44 44
45 #endregion 45 #endregion
46 46
47#region Private fields 47#region Private fields
48 48
49 private HttpContext _httpContext; 49 private HttpContext _httpContext;
50 private LogicalCallContext _callContext; 50 private LogicalCallContext _callContext;
51 51
52 #endregion 52 #endregion
53 53
54 /// <summary> 54 /// <summary>
55 /// Constructor 55 /// Constructor
56 /// </summary> 56 /// </summary>
57 private CallerThreadContext() 57 private CallerThreadContext()
58 { 58 {
59 } 59 }
60 60
61 public bool CapturedCallContext 61 public bool CapturedCallContext
62 { 62 {
63 get 63 get
64 { 64 {
65 return (null != _callContext); 65 return (null != _callContext);
66 } 66 }
67 } 67 }
68 68
69 public bool CapturedHttpContext 69 public bool CapturedHttpContext
70 { 70 {
71 get 71 get
72 { 72 {
73 return (null != _httpContext); 73 return (null != _httpContext);
74 } 74 }
75 } 75 }
76 76
77 /// <summary> 77 /// <summary>
78 /// Captures the current thread context 78 /// Captures the current thread context
79 /// </summary> 79 /// </summary>
80 /// <returns></returns> 80 /// <returns></returns>
81 public static CallerThreadContext Capture( 81 public static CallerThreadContext Capture(
82 bool captureCallContext, 82 bool captureCallContext,
83 bool captureHttpContext) 83 bool captureHttpContext)
84 { 84 {
85 Debug.Assert(captureCallContext || captureHttpContext); 85 Debug.Assert(captureCallContext || captureHttpContext);
86 86
87 CallerThreadContext callerThreadContext = new CallerThreadContext(); 87 CallerThreadContext callerThreadContext = new CallerThreadContext();
88 88
89 // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() 89 // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
90 // Capture Call Context 90 // Capture Call Context
91 if(captureCallContext && (getLogicalCallContextMethodInfo != null)) 91 if(captureCallContext && (getLogicalCallContextMethodInfo != null))
92 { 92 {
93 callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); 93 callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
94 if (callerThreadContext._callContext != null) 94 if (callerThreadContext._callContext != null)
95 { 95 {
96 callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); 96 callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
97 } 97 }
98 } 98 }
99 99
100 // Capture httpContext 100 // Capture httpContext
101 if (captureHttpContext && (null != HttpContext.Current)) 101 if (captureHttpContext && (null != HttpContext.Current))
102 { 102 {
103 callerThreadContext._httpContext = HttpContext.Current; 103 callerThreadContext._httpContext = HttpContext.Current;
104 } 104 }
105 105
106 return callerThreadContext; 106 return callerThreadContext;
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
110 /// Applies the thread context stored earlier 110 /// Applies the thread context stored earlier
111 /// </summary> 111 /// </summary>
112 /// <param name="callerThreadContext"></param> 112 /// <param name="callerThreadContext"></param>
113 public static void Apply(CallerThreadContext callerThreadContext) 113 public static void Apply(CallerThreadContext callerThreadContext)
114 { 114 {
115 if (null == callerThreadContext) 115 if (null == callerThreadContext)
116 { 116 {
117 throw new ArgumentNullException("callerThreadContext"); 117 throw new ArgumentNullException("callerThreadContext");
118 } 118 }
119 119
120 // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() 120 // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
121 // Restore call context 121 // Restore call context
122 if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) 122 if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
123 { 123 {
124 setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); 124 setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
125 } 125 }
126 126
127 // Restore HttpContext 127 // Restore HttpContext
128 if (callerThreadContext._httpContext != null) 128 if (callerThreadContext._httpContext != null)
129 { 129 {
130 HttpContext.Current = callerThreadContext._httpContext; 130 HttpContext.Current = callerThreadContext._httpContext;
131 //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); 131 //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
132 } 132 }
133 } 133 }
134 } 134 }
135 135
136 #endregion 136 #endregion
137} 137}
diff --git a/ThirdParty/SmartThreadPool/EventWaitHandle.cs b/ThirdParty/SmartThreadPool/EventWaitHandle.cs
index 25be07a..b7983cd 100644
--- a/ThirdParty/SmartThreadPool/EventWaitHandle.cs
+++ b/ThirdParty/SmartThreadPool/EventWaitHandle.cs
@@ -36,34 +36,34 @@ namespace Amib.Threading.Internal
36 return waitHandle.WaitOne(millisecondsTimeout, exitContext); 36 return waitHandle.WaitOne(millisecondsTimeout, exitContext);
37 } 37 }
38 38
39 private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles) 39 private static IntPtr[] PrepareNativeHandles(WaitHandle[] waitHandles)
40 { 40 {
41 IntPtr[] nativeHandles = new IntPtr[waitHandles.Length]; 41 IntPtr[] nativeHandles = new IntPtr[waitHandles.Length];
42 for (int i = 0; i < waitHandles.Length; i++) 42 for (int i = 0; i < waitHandles.Length; i++)
43 { 43 {
44 nativeHandles[i] = waitHandles[i].Handle; 44 nativeHandles[i] = waitHandles[i].Handle;
45 } 45 }
46 return nativeHandles; 46 return nativeHandles;
47 } 47 }
48 48
49 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) 49 public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
50 { 50 {
51 uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout; 51 uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
52 52
53 IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles); 53 IntPtr[] nativeHandles = PrepareNativeHandles(waitHandles);
54 54
55 int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, true, timeout); 55 int result = WaitForMultipleObjects((uint)waitHandles.Length, nativeHandles, true, timeout);
56 56
57 if (result == WAIT_TIMEOUT || result == WAIT_FAILED) 57 if (result == WAIT_TIMEOUT || result == WAIT_FAILED)
58 { 58 {
59 return false; 59 return false;
60 } 60 }
61 61
62 return true; 62 return true;
63 } 63 }
64 64
65 65
66 public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) 66 public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
67 { 67 {
68 uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout; 68 uint timeout = millisecondsTimeout < 0 ? INFINITE : (uint)millisecondsTimeout;
69 69
@@ -90,7 +90,7 @@ namespace Amib.Threading.Internal
90 90
91 return WaitAny(waitHandles, millisecondsTimeout, false); 91 return WaitAny(waitHandles, millisecondsTimeout, false);
92 } 92 }
93 93
94 #endregion 94 #endregion
95 95
96 #region External methods 96 #region External methods
diff --git a/ThirdParty/SmartThreadPool/EventWaitHandleFactory.cs b/ThirdParty/SmartThreadPool/EventWaitHandleFactory.cs
index 3c9c849..ece24de 100644
--- a/ThirdParty/SmartThreadPool/EventWaitHandleFactory.cs
+++ b/ThirdParty/SmartThreadPool/EventWaitHandleFactory.cs
@@ -10,7 +10,7 @@ namespace Amib.Threading.Internal
10 /// <summary> 10 /// <summary>
11 /// EventWaitHandleFactory class. 11 /// EventWaitHandleFactory class.
12 /// This is a static class that creates AutoResetEvent and ManualResetEvent objects. 12 /// This is a static class that creates AutoResetEvent and ManualResetEvent objects.
13 /// In WindowCE the WaitForMultipleObjects API fails to use the Handle property 13 /// In WindowCE the WaitForMultipleObjects API fails to use the Handle property
14 /// of XxxResetEvent. It can use only handles that were created by the CreateEvent API. 14 /// of XxxResetEvent. It can use only handles that were created by the CreateEvent API.
15 /// Consequently this class creates the needed XxxResetEvent and replaces the handle if 15 /// Consequently this class creates the needed XxxResetEvent and replaces the handle if
16 /// it's a WindowsCE OS. 16 /// it's a WindowsCE OS.
@@ -57,7 +57,7 @@ namespace Amib.Threading.Internal
57 /// <param name="initialState">The initial state of the event</param> 57 /// <param name="initialState">The initial state of the event</param>
58 private static void ReplaceEventHandle(WaitHandle waitHandle, bool manualReset, bool initialState) 58 private static void ReplaceEventHandle(WaitHandle waitHandle, bool manualReset, bool initialState)
59 { 59 {
60 // Store the old handle 60 // Store the old handle
61 IntPtr oldHandle = waitHandle.Handle; 61 IntPtr oldHandle = waitHandle.Handle;
62 62
63 // Create a new event 63 // Create a new event
@@ -67,7 +67,7 @@ namespace Amib.Threading.Internal
67 waitHandle.Handle = newHandle; 67 waitHandle.Handle = newHandle;
68 68
69 // Close the old event 69 // Close the old event
70 CloseHandle (oldHandle); 70 CloseHandle (oldHandle);
71 } 71 }
72 72
73 [DllImport("coredll.dll", SetLastError = true)] 73 [DllImport("coredll.dll", SetLastError = true)]
diff --git a/ThirdParty/SmartThreadPool/Interfaces.cs b/ThirdParty/SmartThreadPool/Interfaces.cs
index 513422f..8cc23a0 100644
--- a/ThirdParty/SmartThreadPool/Interfaces.cs
+++ b/ThirdParty/SmartThreadPool/Interfaces.cs
@@ -3,18 +3,18 @@ using System.Threading;
3 3
4namespace Amib.Threading 4namespace Amib.Threading
5{ 5{
6 #region Delegates 6 #region Delegates
7 7
8 /// <summary> 8 /// <summary>
9 /// A delegate that represents the method to run as the work item 9 /// A delegate that represents the method to run as the work item
10 /// </summary> 10 /// </summary>
11 /// <param name="state">A state object for the method to run</param> 11 /// <param name="state">A state object for the method to run</param>
12 public delegate object WorkItemCallback(object state); 12 public delegate object WorkItemCallback(object state);
13 13
14 /// <summary> 14 /// <summary>
15 /// A delegate to call after the WorkItemCallback completed 15 /// A delegate to call after the WorkItemCallback completed
16 /// </summary> 16 /// </summary>
17 /// <param name="wir">The work item result object</param> 17 /// <param name="wir">The work item result object</param>
18 public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir); 18 public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
19 19
20 /// <summary> 20 /// <summary>
@@ -23,56 +23,56 @@ namespace Amib.Threading
23 /// <param name="wir">The work item result object</param> 23 /// <param name="wir">The work item result object</param>
24 public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir); 24 public delegate void PostExecuteWorkItemCallback<TResult>(IWorkItemResult<TResult> wir);
25 25
26 /// <summary> 26 /// <summary>
27 /// A delegate to call when a WorkItemsGroup becomes idle 27 /// A delegate to call when a WorkItemsGroup becomes idle
28 /// </summary> 28 /// </summary>
29 /// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param> 29 /// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
30 public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup); 30 public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
31 31
32 /// <summary> 32 /// <summary>
33 /// A delegate to call after a thread is created, but before 33 /// A delegate to call after a thread is created, but before
34 /// it's first use. 34 /// it's first use.
35 /// </summary> 35 /// </summary>
36 public delegate void ThreadInitializationHandler(); 36 public delegate void ThreadInitializationHandler();
37 37
38 /// <summary> 38 /// <summary>
39 /// A delegate to call when a thread is about to exit, after 39 /// A delegate to call when a thread is about to exit, after
40 /// it is no longer belong to the pool. 40 /// it is no longer belong to the pool.
41 /// </summary> 41 /// </summary>
42 public delegate void ThreadTerminationHandler(); 42 public delegate void ThreadTerminationHandler();
43 43
44 #endregion 44 #endregion
45 45
46 #region WorkItem Priority 46 #region WorkItem Priority
47 47
48 /// <summary> 48 /// <summary>
49 /// Defines the availeable priorities of a work item. 49 /// Defines the availeable priorities of a work item.
50 /// The higher the priority a work item has, the sooner 50 /// The higher the priority a work item has, the sooner
51 /// it will be executed. 51 /// it will be executed.
52 /// </summary> 52 /// </summary>
53 public enum WorkItemPriority 53 public enum WorkItemPriority
54 { 54 {
55 Lowest, 55 Lowest,
56 BelowNormal, 56 BelowNormal,
57 Normal, 57 Normal,
58 AboveNormal, 58 AboveNormal,
59 Highest, 59 Highest,
60 } 60 }
61 61
62 #endregion 62 #endregion
63 63
64 #region IWorkItemsGroup interface 64 #region IWorkItemsGroup interface
65 65
66 /// <summary> 66 /// <summary>
67 /// IWorkItemsGroup interface 67 /// IWorkItemsGroup interface
68 /// Created by SmartThreadPool.CreateWorkItemsGroup() 68 /// Created by SmartThreadPool.CreateWorkItemsGroup()
69 /// </summary> 69 /// </summary>
70 public interface IWorkItemsGroup 70 public interface IWorkItemsGroup
71 { 71 {
72 /// <summary> 72 /// <summary>
73 /// Get/Set the name of the WorkItemsGroup 73 /// Get/Set the name of the WorkItemsGroup
74 /// </summary> 74 /// </summary>
75 string Name { get; set; } 75 string Name { get; set; }
76 76
77 /// <summary> 77 /// <summary>
78 /// Get/Set the maximum number of workitem that execute cocurrency on the thread pool 78 /// Get/Set the maximum number of workitem that execute cocurrency on the thread pool
@@ -115,14 +115,14 @@ namespace Amib.Threading
115 /// <summary> 115 /// <summary>
116 /// Wait for all work item to complete. 116 /// Wait for all work item to complete.
117 /// </summary> 117 /// </summary>
118 void WaitForIdle(); 118 void WaitForIdle();
119 119
120 /// <summary> 120 /// <summary>
121 /// Wait for all work item to complete, until timeout expired 121 /// Wait for all work item to complete, until timeout expired
122 /// </summary> 122 /// </summary>
123 /// <param name="timeout">How long to wait for the work items to complete</param> 123 /// <param name="timeout">How long to wait for the work items to complete</param>
124 /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns> 124 /// <returns>Returns true if work items completed within the timeout, otherwise false.</returns>
125 bool WaitForIdle(TimeSpan timeout); 125 bool WaitForIdle(TimeSpan timeout);
126 126
127 /// <summary> 127 /// <summary>
128 /// Wait for all work item to complete, until timeout expired 128 /// Wait for all work item to complete, until timeout expired
@@ -150,7 +150,7 @@ namespace Amib.Threading
150 /// Queue a work item 150 /// Queue a work item
151 /// </summary> 151 /// </summary>
152 /// <param name="callback">A callback to execute</param> 152 /// <param name="callback">A callback to execute</param>
153 /// <returns>Returns a work item result</returns> 153 /// <returns>Returns a work item result</returns>
154 IWorkItemResult QueueWorkItem(WorkItemCallback callback); 154 IWorkItemResult QueueWorkItem(WorkItemCallback callback);
155 155
156 /// <summary> 156 /// <summary>
@@ -166,7 +166,7 @@ namespace Amib.Threading
166 /// </summary> 166 /// </summary>
167 /// <param name="callback">A callback to execute</param> 167 /// <param name="callback">A callback to execute</param>
168 /// <param name="state"> 168 /// <param name="state">
169 /// The context object of the work item. Used for passing arguments to the work item. 169 /// The context object of the work item. Used for passing arguments to the work item.
170 /// </param> 170 /// </param>
171 /// <returns>Returns a work item result</returns> 171 /// <returns>Returns a work item result</returns>
172 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state); 172 IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
@@ -176,7 +176,7 @@ namespace Amib.Threading
176 /// </summary> 176 /// </summary>
177 /// <param name="callback">A callback to execute</param> 177 /// <param name="callback">A callback to execute</param>
178 /// <param name="state"> 178 /// <param name="state">
179 /// The context object of the work item. Used for passing arguments to the work item. 179 /// The context object of the work item. Used for passing arguments to the work item.
180 /// </param> 180 /// </param>
181 /// <param name="workItemPriority">The work item priority</param> 181 /// <param name="workItemPriority">The work item priority</param>
182 /// <returns>Returns a work item result</returns> 182 /// <returns>Returns a work item result</returns>
@@ -187,7 +187,7 @@ namespace Amib.Threading
187 /// </summary> 187 /// </summary>
188 /// <param name="callback">A callback to execute</param> 188 /// <param name="callback">A callback to execute</param>
189 /// <param name="state"> 189 /// <param name="state">
190 /// The context object of the work item. Used for passing arguments to the work item. 190 /// The context object of the work item. Used for passing arguments to the work item.
191 /// </param> 191 /// </param>
192 /// <param name="postExecuteWorkItemCallback"> 192 /// <param name="postExecuteWorkItemCallback">
193 /// A delegate to call after the callback completion 193 /// A delegate to call after the callback completion
@@ -200,7 +200,7 @@ namespace Amib.Threading
200 /// </summary> 200 /// </summary>
201 /// <param name="callback">A callback to execute</param> 201 /// <param name="callback">A callback to execute</param>
202 /// <param name="state"> 202 /// <param name="state">
203 /// The context object of the work item. Used for passing arguments to the work item. 203 /// The context object of the work item. Used for passing arguments to the work item.
204 /// </param> 204 /// </param>
205 /// <param name="postExecuteWorkItemCallback"> 205 /// <param name="postExecuteWorkItemCallback">
206 /// A delegate to call after the callback completion 206 /// A delegate to call after the callback completion
@@ -214,7 +214,7 @@ namespace Amib.Threading
214 /// </summary> 214 /// </summary>
215 /// <param name="callback">A callback to execute</param> 215 /// <param name="callback">A callback to execute</param>
216 /// <param name="state"> 216 /// <param name="state">
217 /// The context object of the work item. Used for passing arguments to the work item. 217 /// The context object of the work item. Used for passing arguments to the work item.
218 /// </param> 218 /// </param>
219 /// <param name="postExecuteWorkItemCallback"> 219 /// <param name="postExecuteWorkItemCallback">
220 /// A delegate to call after the callback completion 220 /// A delegate to call after the callback completion
@@ -228,7 +228,7 @@ namespace Amib.Threading
228 /// </summary> 228 /// </summary>
229 /// <param name="callback">A callback to execute</param> 229 /// <param name="callback">A callback to execute</param>
230 /// <param name="state"> 230 /// <param name="state">
231 /// The context object of the work item. Used for passing arguments to the work item. 231 /// The context object of the work item. Used for passing arguments to the work item.
232 /// </param> 232 /// </param>
233 /// <param name="postExecuteWorkItemCallback"> 233 /// <param name="postExecuteWorkItemCallback">
234 /// A delegate to call after the callback completion 234 /// A delegate to call after the callback completion
@@ -252,7 +252,7 @@ namespace Amib.Threading
252 /// <param name="workItemInfo">Work item information</param> 252 /// <param name="workItemInfo">Work item information</param>
253 /// <param name="callback">A callback to execute</param> 253 /// <param name="callback">A callback to execute</param>
254 /// <param name="state"> 254 /// <param name="state">
255 /// The context object of the work item. Used for passing arguments to the work item. 255 /// The context object of the work item. Used for passing arguments to the work item.
256 /// </param> 256 /// </param>
257 /// <returns>Returns a work item result</returns> 257 /// <returns>Returns a work item result</returns>
258 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state); 258 IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
@@ -328,72 +328,72 @@ namespace Amib.Threading
328 /// <summary> 328 /// <summary>
329 /// Queue a work item. 329 /// Queue a work item.
330 /// </summary> 330 /// </summary>
331 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object. 331 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
332 /// its GetResult() returns a TResult object</returns> 332 /// its GetResult() returns a TResult object</returns>
333 IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func); 333 IWorkItemResult<TResult> QueueWorkItem<TResult>(Func<TResult> func);
334 334
335 /// <summary> 335 /// <summary>
336 /// Queue a work item. 336 /// Queue a work item.
337 /// </summary> 337 /// </summary>
338 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object. 338 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
339 /// its GetResult() returns a TResult object</returns> 339 /// its GetResult() returns a TResult object</returns>
340 IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg); 340 IWorkItemResult<TResult> QueueWorkItem<T, TResult>(Func<T, TResult> func, T arg);
341 341
342 /// <summary> 342 /// <summary>
343 /// Queue a work item. 343 /// Queue a work item.
344 /// </summary> 344 /// </summary>
345 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object. 345 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
346 /// its GetResult() returns a TResult object</returns> 346 /// its GetResult() returns a TResult object</returns>
347 IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2); 347 IWorkItemResult<TResult> QueueWorkItem<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2);
348 348
349 /// <summary> 349 /// <summary>
350 /// Queue a work item. 350 /// Queue a work item.
351 /// </summary> 351 /// </summary>
352 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object. 352 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
353 /// its GetResult() returns a TResult object</returns> 353 /// its GetResult() returns a TResult object</returns>
354 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3); 354 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2, T3 arg3);
355 355
356 /// <summary> 356 /// <summary>
357 /// Queue a work item. 357 /// Queue a work item.
358 /// </summary> 358 /// </summary>
359 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object. 359 /// <returns>Returns a IWorkItemResult&lt;TResult&gt; object.
360 /// its GetResult() returns a TResult object</returns> 360 /// its GetResult() returns a TResult object</returns>
361 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4); 361 IWorkItemResult<TResult> QueueWorkItem<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4);
362 362
363 #endregion 363 #endregion
364 } 364 }
365 365
366 #endregion 366 #endregion
367 367
368 #region CallToPostExecute enumerator 368 #region CallToPostExecute enumerator
369 369
370 [Flags] 370 [Flags]
371 public enum CallToPostExecute 371 public enum CallToPostExecute
372 { 372 {
373 /// <summary> 373 /// <summary>
374 /// Never call to the PostExecute call back 374 /// Never call to the PostExecute call back
375 /// </summary> 375 /// </summary>
376 Never = 0x00, 376 Never = 0x00,
377 377
378 /// <summary> 378 /// <summary>
379 /// Call to the PostExecute only when the work item is cancelled 379 /// Call to the PostExecute only when the work item is cancelled
380 /// </summary> 380 /// </summary>
381 WhenWorkItemCanceled = 0x01, 381 WhenWorkItemCanceled = 0x01,
382 382
383 /// <summary> 383 /// <summary>
384 /// Call to the PostExecute only when the work item is not cancelled 384 /// Call to the PostExecute only when the work item is not cancelled
385 /// </summary> 385 /// </summary>
386 WhenWorkItemNotCanceled = 0x02, 386 WhenWorkItemNotCanceled = 0x02,
387 387
388 /// <summary> 388 /// <summary>
389 /// Always call to the PostExecute 389 /// Always call to the PostExecute
390 /// </summary> 390 /// </summary>
391 Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled, 391 Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
392 } 392 }
393 393
394 #endregion 394 #endregion
395 395
396 #region IWorkItemResult interface 396 #region IWorkItemResult interface
397 397
398 /// <summary> 398 /// <summary>
399 /// The common interface of IWorkItemResult and IWorkItemResult&lt;T&gt; 399 /// The common interface of IWorkItemResult and IWorkItemResult&lt;T&gt;
@@ -421,159 +421,159 @@ namespace Amib.Threading
421 { 421 {
422 } 422 }
423 423
424 /// <summary> 424 /// <summary>
425 /// IWorkItemResult&lt;TResult&gt; interface. 425 /// IWorkItemResult&lt;TResult&gt; interface.
426 /// Created when a Func&lt;TResult&gt; work item is queued. 426 /// Created when a Func&lt;TResult&gt; work item is queued.
427 /// </summary> 427 /// </summary>
428 public interface IWorkItemResult<TResult> : IWaitableResult 428 public interface IWorkItemResult<TResult> : IWaitableResult
429 { 429 {
430 /// <summary> 430 /// <summary>
431 /// Get the result of the work item. 431 /// Get the result of the work item.
432 /// If the work item didn't run yet then the caller waits. 432 /// If the work item didn't run yet then the caller waits.
433 /// </summary> 433 /// </summary>
434 /// <returns>The result of the work item</returns> 434 /// <returns>The result of the work item</returns>
435 TResult GetResult(); 435 TResult GetResult();
436 436
437 /// <summary> 437 /// <summary>
438 /// Get the result of the work item. 438 /// Get the result of the work item.
439 /// If the work item didn't run yet then the caller waits until timeout. 439 /// If the work item didn't run yet then the caller waits until timeout.
440 /// </summary> 440 /// </summary>
441 /// <returns>The result of the work item</returns> 441 /// <returns>The result of the work item</returns>
442 /// On timeout throws WorkItemTimeoutException 442 /// On timeout throws WorkItemTimeoutException
443 TResult GetResult(
444 int millisecondsTimeout,
445 bool exitContext);
446
447 /// <summary>
448 /// Get the result of the work item.
449 /// If the work item didn't run yet then the caller waits until timeout.
450 /// </summary>
451 /// <returns>The result of the work item</returns>
452 /// On timeout throws WorkItemTimeoutException
453 TResult GetResult(
454 TimeSpan timeout,
455 bool exitContext);
456
457 /// <summary>
458 /// Get the result of the work item.
459 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
460 /// </summary>
461 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
462 /// <param name="exitContext">
463 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
464 /// </param>
465 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
466 /// <returns>The result of the work item</returns>
467 /// On timeout throws WorkItemTimeoutException
468 /// On cancel throws WorkItemCancelException
469 TResult GetResult(
470 int millisecondsTimeout,
471 bool exitContext,
472 WaitHandle cancelWaitHandle);
473
474 /// <summary>
475 /// Get the result of the work item.
476 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
477 /// </summary>
478 /// <returns>The result of the work item</returns>
479 /// On timeout throws WorkItemTimeoutException
480 /// On cancel throws WorkItemCancelException
443 TResult GetResult( 481 TResult GetResult(
444 int millisecondsTimeout, 482 TimeSpan timeout,
445 bool exitContext); 483 bool exitContext,
446 484 WaitHandle cancelWaitHandle);
447 /// <summary> 485
448 /// Get the result of the work item. 486 /// <summary>
449 /// If the work item didn't run yet then the caller waits until timeout. 487 /// Get the result of the work item.
450 /// </summary> 488 /// If the work item didn't run yet then the caller waits.
451 /// <returns>The result of the work item</returns> 489 /// </summary>
452 /// On timeout throws WorkItemTimeoutException 490 /// <param name="e">Filled with the exception if one was thrown</param>
453 TResult GetResult( 491 /// <returns>The result of the work item</returns>
454 TimeSpan timeout,
455 bool exitContext);
456
457 /// <summary>
458 /// Get the result of the work item.
459 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
460 /// </summary>
461 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
462 /// <param name="exitContext">
463 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
464 /// </param>
465 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
466 /// <returns>The result of the work item</returns>
467 /// On timeout throws WorkItemTimeoutException
468 /// On cancel throws WorkItemCancelException
469 TResult GetResult(
470 int millisecondsTimeout,
471 bool exitContext,
472 WaitHandle cancelWaitHandle);
473
474 /// <summary>
475 /// Get the result of the work item.
476 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
477 /// </summary>
478 /// <returns>The result of the work item</returns>
479 /// On timeout throws WorkItemTimeoutException
480 /// On cancel throws WorkItemCancelException
481 TResult GetResult(
482 TimeSpan timeout,
483 bool exitContext,
484 WaitHandle cancelWaitHandle);
485
486 /// <summary>
487 /// Get the result of the work item.
488 /// If the work item didn't run yet then the caller waits.
489 /// </summary>
490 /// <param name="e">Filled with the exception if one was thrown</param>
491 /// <returns>The result of the work item</returns>
492 TResult GetResult(out Exception e); 492 TResult GetResult(out Exception e);
493 493
494 /// <summary> 494 /// <summary>
495 /// Get the result of the work item. 495 /// Get the result of the work item.
496 /// If the work item didn't run yet then the caller waits until timeout. 496 /// If the work item didn't run yet then the caller waits until timeout.
497 /// </summary> 497 /// </summary>
498 /// <param name="millisecondsTimeout"></param> 498 /// <param name="millisecondsTimeout"></param>
499 /// <param name="exitContext"></param> 499 /// <param name="exitContext"></param>
500 /// <param name="e">Filled with the exception if one was thrown</param> 500 /// <param name="e">Filled with the exception if one was thrown</param>
501 /// <returns>The result of the work item</returns> 501 /// <returns>The result of the work item</returns>
502 /// On timeout throws WorkItemTimeoutException 502 /// On timeout throws WorkItemTimeoutException
503 TResult GetResult(
504 int millisecondsTimeout,
505 bool exitContext,
506 out Exception e);
507
508 /// <summary>
509 /// Get the result of the work item.
510 /// If the work item didn't run yet then the caller waits until timeout.
511 /// </summary>
512 /// <param name="exitContext"></param>
513 /// <param name="e">Filled with the exception if one was thrown</param>
514 /// <param name="timeout"></param>
515 /// <returns>The result of the work item</returns>
516 /// On timeout throws WorkItemTimeoutException
517 TResult GetResult(
518 TimeSpan timeout,
519 bool exitContext,
520 out Exception e);
521
522 /// <summary>
523 /// Get the result of the work item.
524 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
525 /// </summary>
526 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
527 /// <param name="exitContext">
528 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
529 /// </param>
530 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
531 /// <param name="e">Filled with the exception if one was thrown</param>
532 /// <returns>The result of the work item</returns>
533 /// On timeout throws WorkItemTimeoutException
534 /// On cancel throws WorkItemCancelException
535 TResult GetResult(
536 int millisecondsTimeout,
537 bool exitContext,
538 WaitHandle cancelWaitHandle,
539 out Exception e);
540
541 /// <summary>
542 /// Get the result of the work item.
543 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
544 /// </summary>
545 /// <returns>The result of the work item</returns>
546 /// <param name="cancelWaitHandle"></param>
547 /// <param name="e">Filled with the exception if one was thrown</param>
548 /// <param name="timeout"></param>
549 /// <param name="exitContext"></param>
550 /// On timeout throws WorkItemTimeoutException
551 /// On cancel throws WorkItemCancelException
503 TResult GetResult( 552 TResult GetResult(
504 int millisecondsTimeout, 553 TimeSpan timeout,
505 bool exitContext, 554 bool exitContext,
506 out Exception e); 555 WaitHandle cancelWaitHandle,
507 556 out Exception e);
508 /// <summary> 557
509 /// Get the result of the work item. 558 /// <summary>
510 /// If the work item didn't run yet then the caller waits until timeout. 559 /// Gets an indication whether the asynchronous operation has completed.
511 /// </summary> 560 /// </summary>
512 /// <param name="exitContext"></param> 561 bool IsCompleted { get; }
513 /// <param name="e">Filled with the exception if one was thrown</param> 562
514 /// <param name="timeout"></param> 563 /// <summary>
515 /// <returns>The result of the work item</returns> 564 /// Gets an indication whether the asynchronous operation has been canceled.
516 /// On timeout throws WorkItemTimeoutException 565 /// </summary>
517 TResult GetResult( 566 bool IsCanceled { get; }
518 TimeSpan timeout, 567
519 bool exitContext, 568 /// <summary>
520 out Exception e); 569 /// Gets the user-defined object that contains context data
521
522 /// <summary>
523 /// Get the result of the work item.
524 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
525 /// </summary>
526 /// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
527 /// <param name="exitContext">
528 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
529 /// </param>
530 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
531 /// <param name="e">Filled with the exception if one was thrown</param>
532 /// <returns>The result of the work item</returns>
533 /// On timeout throws WorkItemTimeoutException
534 /// On cancel throws WorkItemCancelException
535 TResult GetResult(
536 int millisecondsTimeout,
537 bool exitContext,
538 WaitHandle cancelWaitHandle,
539 out Exception e);
540
541 /// <summary>
542 /// Get the result of the work item.
543 /// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
544 /// </summary>
545 /// <returns>The result of the work item</returns>
546 /// <param name="cancelWaitHandle"></param>
547 /// <param name="e">Filled with the exception if one was thrown</param>
548 /// <param name="timeout"></param>
549 /// <param name="exitContext"></param>
550 /// On timeout throws WorkItemTimeoutException
551 /// On cancel throws WorkItemCancelException
552 TResult GetResult(
553 TimeSpan timeout,
554 bool exitContext,
555 WaitHandle cancelWaitHandle,
556 out Exception e);
557
558 /// <summary>
559 /// Gets an indication whether the asynchronous operation has completed.
560 /// </summary>
561 bool IsCompleted { get; }
562
563 /// <summary>
564 /// Gets an indication whether the asynchronous operation has been canceled.
565 /// </summary>
566 bool IsCanceled { get; }
567
568 /// <summary>
569 /// Gets the user-defined object that contains context data
570 /// for the work item method. 570 /// for the work item method.
571 /// </summary> 571 /// </summary>
572 object State { get; } 572 object State { get; }
573 573
574 /// <summary> 574 /// <summary>
575 /// Same as Cancel(false). 575 /// Same as Cancel(false).
576 /// </summary> 576 /// </summary>
577 bool Cancel(); 577 bool Cancel();
578 578
579 /// <summary> 579 /// <summary>
@@ -582,7 +582,7 @@ namespace Amib.Threading
582 /// If the work item is completed, it will remain completed 582 /// If the work item is completed, it will remain completed
583 /// If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled 583 /// If the work item is in progress then the user can check the SmartThreadPool.IsWorkItemCanceled
584 /// property to check if the work item has been cancelled. If the abortExecution is set to true then 584 /// property to check if the work item has been cancelled. If the abortExecution is set to true then
585 /// the Smart Thread Pool will send an AbortException to the running thread to stop the execution 585 /// the Smart Thread Pool will send an AbortException to the running thread to stop the execution
586 /// of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException. 586 /// of the work item. When an in progress work item is canceled its GetResult will throw WorkItemCancelException.
587 /// If the work item is already cancelled it will remain cancelled 587 /// If the work item is already cancelled it will remain cancelled
588 /// </summary> 588 /// </summary>
@@ -590,23 +590,23 @@ namespace Amib.Threading
590 /// <returns>Returns true if the work item was not completed, otherwise false.</returns> 590 /// <returns>Returns true if the work item was not completed, otherwise false.</returns>
591 bool Cancel(bool abortExecution); 591 bool Cancel(bool abortExecution);
592 592
593 /// <summary> 593 /// <summary>
594 /// Get the work item's priority 594 /// Get the work item's priority
595 /// </summary> 595 /// </summary>
596 WorkItemPriority WorkItemPriority { get; } 596 WorkItemPriority WorkItemPriority { get; }
597 597
598 /// <summary> 598 /// <summary>
599 /// Return the result, same as GetResult() 599 /// Return the result, same as GetResult()
600 /// </summary> 600 /// </summary>
601 TResult Result { get; } 601 TResult Result { get; }
602 602
603 /// <summary> 603 /// <summary>
604 /// Returns the exception if occured otherwise returns null. 604 /// Returns the exception if occured otherwise returns null.
605 /// </summary> 605 /// </summary>
606 object Exception { get; } 606 object Exception { get; }
607 } 607 }
608 608
609 #endregion 609 #endregion
610 610
611 #region .NET 3.5 611 #region .NET 3.5
612 612
diff --git a/ThirdParty/SmartThreadPool/InternalInterfaces.cs b/ThirdParty/SmartThreadPool/InternalInterfaces.cs
index 0072e10..3055117 100644
--- a/ThirdParty/SmartThreadPool/InternalInterfaces.cs
+++ b/ThirdParty/SmartThreadPool/InternalInterfaces.cs
@@ -16,7 +16,7 @@ namespace Amib.Threading.Internal
16 { 16 {
17 /// <summary> 17 /// <summary>
18 /// This method is intent for internal use. 18 /// This method is intent for internal use.
19 /// </summary> 19 /// </summary>
20 IWorkItemResult GetWorkItemResult(); 20 IWorkItemResult GetWorkItemResult();
21 } 21 }
22 22
diff --git a/ThirdParty/SmartThreadPool/PriorityQueue.cs b/ThirdParty/SmartThreadPool/PriorityQueue.cs
index 409c879..3ea6084 100644
--- a/ThirdParty/SmartThreadPool/PriorityQueue.cs
+++ b/ThirdParty/SmartThreadPool/PriorityQueue.cs
@@ -5,235 +5,235 @@ using System.Diagnostics;
5 5
6namespace Amib.Threading.Internal 6namespace Amib.Threading.Internal
7{ 7{
8 #region PriorityQueue class 8 #region PriorityQueue class
9 9
10 /// <summary> 10 /// <summary>
11 /// PriorityQueue class 11 /// PriorityQueue class
12 /// This class is not thread safe because we use external lock 12 /// This class is not thread safe because we use external lock
13 /// </summary> 13 /// </summary>
14 public sealed class PriorityQueue : IEnumerable 14 public sealed class PriorityQueue : IEnumerable
15 { 15 {
16 #region Private members 16 #region Private members
17 17
18 /// <summary> 18 /// <summary>
19 /// The number of queues, there is one for each type of priority 19 /// The number of queues, there is one for each type of priority
20 /// </summary> 20 /// </summary>
21 private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1; 21 private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
22 22
23 /// <summary> 23 /// <summary>
24 /// Work items queues. There is one for each type of priority 24 /// Work items queues. There is one for each type of priority
25 /// </summary> 25 /// </summary>
26 private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount]; 26 private readonly LinkedList<IHasWorkItemPriority>[] _queues = new LinkedList<IHasWorkItemPriority>[_queuesCount];
27 27
28 /// <summary> 28 /// <summary>
29 /// The total number of work items within the queues 29 /// The total number of work items within the queues
30 /// </summary> 30 /// </summary>
31 private int _workItemsCount; 31 private int _workItemsCount;
32 32
33 /// <summary> 33 /// <summary>
34 /// Use with IEnumerable interface 34 /// Use with IEnumerable interface
35 /// </summary> 35 /// </summary>
36 private int _version; 36 private int _version;
37 37
38 #endregion 38 #endregion
39 39
40 #region Contructor 40 #region Contructor
41 41
42 public PriorityQueue() 42 public PriorityQueue()
43 { 43 {
44 for(int i = 0; i < _queues.Length; ++i) 44 for(int i = 0; i < _queues.Length; ++i)
45 { 45 {
46 _queues[i] = new LinkedList<IHasWorkItemPriority>(); 46 _queues[i] = new LinkedList<IHasWorkItemPriority>();
47 } 47 }
48 } 48 }
49 49
50 #endregion 50 #endregion
51 51
52 #region Methods 52 #region Methods
53 53
54 /// <summary> 54 /// <summary>
55 /// Enqueue a work item. 55 /// Enqueue a work item.
56 /// </summary> 56 /// </summary>
57 /// <param name="workItem">A work item</param> 57 /// <param name="workItem">A work item</param>
58 public void Enqueue(IHasWorkItemPriority workItem) 58 public void Enqueue(IHasWorkItemPriority workItem)
59 { 59 {
60 Debug.Assert(null != workItem); 60 Debug.Assert(null != workItem);
61 61
62 int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1; 62 int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
63 Debug.Assert(queueIndex >= 0); 63 Debug.Assert(queueIndex >= 0);
64 Debug.Assert(queueIndex < _queuesCount); 64 Debug.Assert(queueIndex < _queuesCount);
65 65
66 _queues[queueIndex].AddLast(workItem); 66 _queues[queueIndex].AddLast(workItem);
67 ++_workItemsCount; 67 ++_workItemsCount;
68 ++_version; 68 ++_version;
69 } 69 }
70 70
71 /// <summary> 71 /// <summary>
72 /// Dequeque a work item. 72 /// Dequeque a work item.
73 /// </summary> 73 /// </summary>
74 /// <returns>Returns the next work item</returns> 74 /// <returns>Returns the next work item</returns>
75 public IHasWorkItemPriority Dequeue() 75 public IHasWorkItemPriority Dequeue()
76 { 76 {
77 IHasWorkItemPriority workItem = null; 77 IHasWorkItemPriority workItem = null;
78 78
79 if(_workItemsCount > 0) 79 if(_workItemsCount > 0)
80 { 80 {
81 int queueIndex = GetNextNonEmptyQueue(-1); 81 int queueIndex = GetNextNonEmptyQueue(-1);
82 Debug.Assert(queueIndex >= 0); 82 Debug.Assert(queueIndex >= 0);
83 workItem = _queues[queueIndex].First.Value; 83 workItem = _queues[queueIndex].First.Value;
84 _queues[queueIndex].RemoveFirst(); 84 _queues[queueIndex].RemoveFirst();
85 Debug.Assert(null != workItem); 85 Debug.Assert(null != workItem);
86 --_workItemsCount; 86 --_workItemsCount;
87 ++_version; 87 ++_version;
88 } 88 }
89 89
90 return workItem; 90 return workItem;
91 } 91 }
92 92
93 /// <summary> 93 /// <summary>
94 /// Find the next non empty queue starting at queue queueIndex+1 94 /// Find the next non empty queue starting at queue queueIndex+1
95 /// </summary> 95 /// </summary>
96 /// <param name="queueIndex">The index-1 to start from</param> 96 /// <param name="queueIndex">The index-1 to start from</param>
97 /// <returns> 97 /// <returns>
98 /// The index of the next non empty queue or -1 if all the queues are empty 98 /// The index of the next non empty queue or -1 if all the queues are empty
99 /// </returns> 99 /// </returns>
100 private int GetNextNonEmptyQueue(int queueIndex) 100 private int GetNextNonEmptyQueue(int queueIndex)
101 { 101 {
102 for(int i = queueIndex+1; i < _queuesCount; ++i) 102 for(int i = queueIndex+1; i < _queuesCount; ++i)
103 { 103 {
104 if(_queues[i].Count > 0) 104 if(_queues[i].Count > 0)
105 { 105 {
106 return i; 106 return i;
107 } 107 }
108 } 108 }
109 return -1; 109 return -1;
110 } 110 }
111 111
112 /// <summary> 112 /// <summary>
113 /// The number of work items 113 /// The number of work items
114 /// </summary> 114 /// </summary>
115 public int Count 115 public int Count
116 { 116 {
117 get 117 get
118 { 118 {
119 return _workItemsCount; 119 return _workItemsCount;
120 } 120 }
121 } 121 }
122 122
123 /// <summary> 123 /// <summary>
124 /// Clear all the work items 124 /// Clear all the work items
125 /// </summary> 125 /// </summary>
126 public void Clear() 126 public void Clear()
127 { 127 {
128 if (_workItemsCount > 0) 128 if (_workItemsCount > 0)
129 { 129 {
130 foreach(LinkedList<IHasWorkItemPriority> queue in _queues) 130 foreach(LinkedList<IHasWorkItemPriority> queue in _queues)
131 { 131 {
132 queue.Clear(); 132 queue.Clear();
133 } 133 }
134 _workItemsCount = 0; 134 _workItemsCount = 0;
135 ++_version; 135 ++_version;
136 } 136 }
137 } 137 }
138 138
139 #endregion 139 #endregion
140 140
141 #region IEnumerable Members 141 #region IEnumerable Members
142 142
143 /// <summary> 143 /// <summary>
144 /// Returns an enumerator to iterate over the work items 144 /// Returns an enumerator to iterate over the work items
145 /// </summary> 145 /// </summary>
146 /// <returns>Returns an enumerator</returns> 146 /// <returns>Returns an enumerator</returns>
147 public IEnumerator GetEnumerator() 147 public IEnumerator GetEnumerator()
148 { 148 {
149 return new PriorityQueueEnumerator(this); 149 return new PriorityQueueEnumerator(this);
150 } 150 }
151 151
152 #endregion 152 #endregion
153 153
154 #region PriorityQueueEnumerator 154 #region PriorityQueueEnumerator
155 155
156 /// <summary> 156 /// <summary>
157 /// The class the implements the enumerator 157 /// The class the implements the enumerator
158 /// </summary> 158 /// </summary>
159 private class PriorityQueueEnumerator : IEnumerator 159 private class PriorityQueueEnumerator : IEnumerator
160 { 160 {
161 private readonly PriorityQueue _priorityQueue; 161 private readonly PriorityQueue _priorityQueue;
162 private int _version; 162 private int _version;
163 private int _queueIndex; 163 private int _queueIndex;
164 private IEnumerator _enumerator; 164 private IEnumerator _enumerator;
165 165
166 public PriorityQueueEnumerator(PriorityQueue priorityQueue) 166 public PriorityQueueEnumerator(PriorityQueue priorityQueue)
167 { 167 {
168 _priorityQueue = priorityQueue; 168 _priorityQueue = priorityQueue;
169 _version = _priorityQueue._version; 169 _version = _priorityQueue._version;
170 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); 170 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
171 if (_queueIndex >= 0) 171 if (_queueIndex >= 0)
172 { 172 {
173 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); 173 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
174 } 174 }
175 else 175 else
176 { 176 {
177 _enumerator = null; 177 _enumerator = null;
178 } 178 }
179 } 179 }
180 180
181 #region IEnumerator Members 181 #region IEnumerator Members
182 182
183 public void Reset() 183 public void Reset()
184 { 184 {
185 _version = _priorityQueue._version; 185 _version = _priorityQueue._version;
186 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1); 186 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
187 if (_queueIndex >= 0) 187 if (_queueIndex >= 0)
188 { 188 {
189 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); 189 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
190 } 190 }
191 else 191 else
192 { 192 {
193 _enumerator = null; 193 _enumerator = null;
194 } 194 }
195 } 195 }
196 196
197 public object Current 197 public object Current
198 { 198 {
199 get 199 get
200 { 200 {
201 Debug.Assert(null != _enumerator); 201 Debug.Assert(null != _enumerator);
202 return _enumerator.Current; 202 return _enumerator.Current;
203 } 203 }
204 } 204 }
205 205
206 public bool MoveNext() 206 public bool MoveNext()
207 { 207 {
208 if (null == _enumerator) 208 if (null == _enumerator)
209 { 209 {
210 return false; 210 return false;
211 } 211 }
212 212
213 if(_version != _priorityQueue._version) 213 if(_version != _priorityQueue._version)
214 { 214 {
215 throw new InvalidOperationException("The collection has been modified"); 215 throw new InvalidOperationException("The collection has been modified");
216 216
217 } 217 }
218 if (!_enumerator.MoveNext()) 218 if (!_enumerator.MoveNext())
219 { 219 {
220 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex); 220 _queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
221 if(-1 == _queueIndex) 221 if(-1 == _queueIndex)
222 { 222 {
223 return false; 223 return false;
224 } 224 }
225 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator(); 225 _enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
226 _enumerator.MoveNext(); 226 _enumerator.MoveNext();
227 return true; 227 return true;
228 } 228 }
229 return true; 229 return true;
230 } 230 }
231 231
232 #endregion 232 #endregion
233 } 233 }
234 234
235 #endregion 235 #endregion
236 } 236 }
237 237
238 #endregion 238 #endregion
239} 239}
diff --git a/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs b/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs
index 0663d1d..bd68499 100644
--- a/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs
+++ b/ThirdParty/SmartThreadPool/STPPerformanceCounter.cs
@@ -26,188 +26,188 @@ namespace Amib.Threading.Internal
26#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) 26#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
27 27
28 internal enum STPPerformanceCounterType 28 internal enum STPPerformanceCounterType
29 { 29 {
30 // Fields 30 // Fields
31 ActiveThreads = 0, 31 ActiveThreads = 0,
32 InUseThreads = 1, 32 InUseThreads = 1,
33 OverheadThreads = 2, 33 OverheadThreads = 2,
34 OverheadThreadsPercent = 3, 34 OverheadThreadsPercent = 3,
35 OverheadThreadsPercentBase = 4, 35 OverheadThreadsPercentBase = 4,
36 36
37 WorkItems = 5, 37 WorkItems = 5,
38 WorkItemsInQueue = 6, 38 WorkItemsInQueue = 6,
39 WorkItemsProcessed = 7, 39 WorkItemsProcessed = 7,
40 40
41 WorkItemsQueuedPerSecond = 8, 41 WorkItemsQueuedPerSecond = 8,
42 WorkItemsProcessedPerSecond = 9, 42 WorkItemsProcessedPerSecond = 9,
43 43
44 AvgWorkItemWaitTime = 10, 44 AvgWorkItemWaitTime = 10,
45 AvgWorkItemWaitTimeBase = 11, 45 AvgWorkItemWaitTimeBase = 11,
46 46
47 AvgWorkItemProcessTime = 12, 47 AvgWorkItemProcessTime = 12,
48 AvgWorkItemProcessTimeBase = 13, 48 AvgWorkItemProcessTimeBase = 13,
49 49
50 WorkItemsGroups = 14, 50 WorkItemsGroups = 14,
51 51
52 LastCounter = 14, 52 LastCounter = 14,
53 } 53 }
54 54
55 55
56 /// <summary> 56 /// <summary>
57 /// Summary description for STPPerformanceCounter. 57 /// Summary description for STPPerformanceCounter.
58 /// </summary> 58 /// </summary>
59 internal class STPPerformanceCounter 59 internal class STPPerformanceCounter
60 { 60 {
61 // Fields 61 // Fields
62 private readonly PerformanceCounterType _pcType; 62 private readonly PerformanceCounterType _pcType;
63 protected string _counterHelp; 63 protected string _counterHelp;
64 protected string _counterName; 64 protected string _counterName;
65 65
66 // Methods 66 // Methods
67 public STPPerformanceCounter( 67 public STPPerformanceCounter(
68 string counterName, 68 string counterName,
69 string counterHelp, 69 string counterHelp,
70 PerformanceCounterType pcType) 70 PerformanceCounterType pcType)
71 { 71 {
72 _counterName = counterName; 72 _counterName = counterName;
73 _counterHelp = counterHelp; 73 _counterHelp = counterHelp;
74 _pcType = pcType; 74 _pcType = pcType;
75 } 75 }
76 76
77 public void AddCounterToCollection(CounterCreationDataCollection counterData) 77 public void AddCounterToCollection(CounterCreationDataCollection counterData)
78 { 78 {
79 CounterCreationData counterCreationData = new CounterCreationData( 79 CounterCreationData counterCreationData = new CounterCreationData(
80 _counterName, 80 _counterName,
81 _counterHelp, 81 _counterHelp,
82 _pcType); 82 _pcType);
83 83
84 counterData.Add(counterCreationData); 84 counterData.Add(counterCreationData);
85 } 85 }
86 86
87 // Properties 87 // Properties
88 public string Name 88 public string Name
89 { 89 {
90 get 90 get
91 { 91 {
92 return _counterName; 92 return _counterName;
93 } 93 }
94 } 94 }
95 } 95 }
96 96
97 internal class STPPerformanceCounters 97 internal class STPPerformanceCounters
98 { 98 {
99 // Fields 99 // Fields
100 internal STPPerformanceCounter[] _stpPerformanceCounters; 100 internal STPPerformanceCounter[] _stpPerformanceCounters;
101 private static readonly STPPerformanceCounters _instance; 101 private static readonly STPPerformanceCounters _instance;
102 internal const string _stpCategoryHelp = "SmartThreadPool performance counters"; 102 internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
103 internal const string _stpCategoryName = "SmartThreadPool"; 103 internal const string _stpCategoryName = "SmartThreadPool";
104 104
105 // Methods 105 // Methods
106 static STPPerformanceCounters() 106 static STPPerformanceCounters()
107 { 107 {
108 _instance = new STPPerformanceCounters(); 108 _instance = new STPPerformanceCounters();
109 } 109 }
110 110
111 private STPPerformanceCounters() 111 private STPPerformanceCounters()
112 { 112 {
113 STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[] 113 STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
114 { 114 {
115 new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32), 115 new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
116 new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32), 116 new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
117 new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32), 117 new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
118 new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction), 118 new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
119 new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase), 119 new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
120 120
121 new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32), 121 new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
122 new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32), 122 new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
123 new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32), 123 new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
124 124
125 new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32), 125 new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
126 new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32), 126 new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
127 127
128 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), 128 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),
129 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), 129 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),
130 130
131 new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64), 131 new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
132 new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase), 132 new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
133 133
134 new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32), 134 new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
135 }; 135 };
136 136
137 _stpPerformanceCounters = stpPerformanceCounters; 137 _stpPerformanceCounters = stpPerformanceCounters;
138 SetupCategory(); 138 SetupCategory();
139 } 139 }
140 140
141 private void SetupCategory() 141 private void SetupCategory()
142 { 142 {
143 if (!PerformanceCounterCategory.Exists(_stpCategoryName)) 143 if (!PerformanceCounterCategory.Exists(_stpCategoryName))
144 { 144 {
145 CounterCreationDataCollection counters = new CounterCreationDataCollection(); 145 CounterCreationDataCollection counters = new CounterCreationDataCollection();
146 146
147 for (int i = 0; i < _stpPerformanceCounters.Length; i++) 147 for (int i = 0; i < _stpPerformanceCounters.Length; i++)
148 { 148 {
149 _stpPerformanceCounters[i].AddCounterToCollection(counters); 149 _stpPerformanceCounters[i].AddCounterToCollection(counters);
150 } 150 }
151 151
152 PerformanceCounterCategory.Create( 152 PerformanceCounterCategory.Create(
153 _stpCategoryName, 153 _stpCategoryName,
154 _stpCategoryHelp, 154 _stpCategoryHelp,
155 PerformanceCounterCategoryType.MultiInstance, 155 PerformanceCounterCategoryType.MultiInstance,
156 counters); 156 counters);
157 157
158 } 158 }
159 } 159 }
160 160
161 // Properties 161 // Properties
162 public static STPPerformanceCounters Instance 162 public static STPPerformanceCounters Instance
163 { 163 {
164 get 164 get
165 { 165 {
166 return _instance; 166 return _instance;
167 } 167 }
168 } 168 }
169 } 169 }
170 170
171 internal class STPInstancePerformanceCounter : IDisposable 171 internal class STPInstancePerformanceCounter : IDisposable
172 { 172 {
173 // Fields 173 // Fields
174 private bool _isDisposed; 174 private bool _isDisposed;
175 private PerformanceCounter _pcs; 175 private PerformanceCounter _pcs;
176 176
177 // Methods 177 // Methods
178 protected STPInstancePerformanceCounter() 178 protected STPInstancePerformanceCounter()
179 { 179 {
180 _isDisposed = false; 180 _isDisposed = false;
181 } 181 }
182 182
183 public STPInstancePerformanceCounter( 183 public STPInstancePerformanceCounter(
184 string instance, 184 string instance,
185 STPPerformanceCounterType spcType) : this() 185 STPPerformanceCounterType spcType) : this()
186 { 186 {
187 STPPerformanceCounters counters = STPPerformanceCounters.Instance; 187 STPPerformanceCounters counters = STPPerformanceCounters.Instance;
188 _pcs = new PerformanceCounter( 188 _pcs = new PerformanceCounter(
189 STPPerformanceCounters._stpCategoryName, 189 STPPerformanceCounters._stpCategoryName,
190 counters._stpPerformanceCounters[(int) spcType].Name, 190 counters._stpPerformanceCounters[(int) spcType].Name,
191 instance, 191 instance,
192 false); 192 false);
193 _pcs.RawValue = _pcs.RawValue; 193 _pcs.RawValue = _pcs.RawValue;
194 } 194 }
195 195
196 196
197 public void Close() 197 public void Close()
198 { 198 {
199 if (_pcs != null) 199 if (_pcs != null)
200 { 200 {
201 _pcs.RemoveInstance(); 201 _pcs.RemoveInstance();
202 _pcs.Close(); 202 _pcs.Close();
203 _pcs = null; 203 _pcs = null;
204 } 204 }
205 } 205 }
206 206
207 public void Dispose() 207 public void Dispose()
208 { 208 {
209 Dispose(true); 209 Dispose(true);
210 } 210 }
211 211
212 public virtual void Dispose(bool disposing) 212 public virtual void Dispose(bool disposing)
213 { 213 {
@@ -220,90 +220,90 @@ namespace Amib.Threading.Internal
220 } 220 }
221 _isDisposed = true; 221 _isDisposed = true;
222 } 222 }
223 223
224 public virtual void Increment() 224 public virtual void Increment()
225 { 225 {
226 _pcs.Increment(); 226 _pcs.Increment();
227 } 227 }
228 228
229 public virtual void IncrementBy(long val) 229 public virtual void IncrementBy(long val)
230 { 230 {
231 _pcs.IncrementBy(val); 231 _pcs.IncrementBy(val);
232 } 232 }
233 233
234 public virtual void Set(long val) 234 public virtual void Set(long val)
235 { 235 {
236 _pcs.RawValue = val; 236 _pcs.RawValue = val;
237 } 237 }
238 } 238 }
239 239
240 internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter 240 internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
241 { 241 {
242 // Methods 242 // Methods
243 public override void Increment() {} 243 public override void Increment() {}
244 public override void IncrementBy(long value) {} 244 public override void IncrementBy(long value) {}
245 public override void Set(long val) {} 245 public override void Set(long val) {}
246 } 246 }
247 247
248 248
249 249
250 internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters 250 internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters
251 { 251 {
252 private bool _isDisposed; 252 private bool _isDisposed;
253 // Fields 253 // Fields
254 private STPInstancePerformanceCounter[] _pcs; 254 private STPInstancePerformanceCounter[] _pcs;
255 private static readonly STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter; 255 private static readonly STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
256 256
257 // Methods 257 // Methods
258 static STPInstancePerformanceCounters() 258 static STPInstancePerformanceCounters()
259 { 259 {
260 _stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter(); 260 _stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
261 } 261 }
262 262
263 public STPInstancePerformanceCounters(string instance) 263 public STPInstancePerformanceCounters(string instance)
264 { 264 {
265 _isDisposed = false; 265 _isDisposed = false;
266 _pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter]; 266 _pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
267 267
268 // Call the STPPerformanceCounters.Instance so the static constructor will 268 // Call the STPPerformanceCounters.Instance so the static constructor will
269 // intialize the STPPerformanceCounters singleton. 269 // intialize the STPPerformanceCounters singleton.
270 STPPerformanceCounters.Instance.GetHashCode(); 270 STPPerformanceCounters.Instance.GetHashCode();
271 271
272 for (int i = 0; i < _pcs.Length; i++) 272 for (int i = 0; i < _pcs.Length; i++)
273 { 273 {
274 if (instance != null) 274 if (instance != null)
275 { 275 {
276 _pcs[i] = new STPInstancePerformanceCounter( 276 _pcs[i] = new STPInstancePerformanceCounter(
277 instance, 277 instance,
278 (STPPerformanceCounterType) i); 278 (STPPerformanceCounterType) i);
279 } 279 }
280 else 280 else
281 { 281 {
282 _pcs[i] = _stpInstanceNullPerformanceCounter; 282 _pcs[i] = _stpInstanceNullPerformanceCounter;
283 } 283 }
284 } 284 }
285 } 285 }
286 286
287 287
288 public void Close() 288 public void Close()
289 { 289 {
290 if (null != _pcs) 290 if (null != _pcs)
291 { 291 {
292 for (int i = 0; i < _pcs.Length; i++) 292 for (int i = 0; i < _pcs.Length; i++)
293 { 293 {
294 if (null != _pcs[i]) 294 if (null != _pcs[i])
295 { 295 {
296 _pcs[i].Dispose(); 296 _pcs[i].Dispose();
297 } 297 }
298 } 298 }
299 _pcs = null; 299 _pcs = null;
300 } 300 }
301 } 301 }
302 302
303 public void Dispose() 303 public void Dispose()
304 { 304 {
305 Dispose(true); 305 Dispose(true);
306 } 306 }
307 307
308 public virtual void Dispose(bool disposing) 308 public virtual void Dispose(bool disposing)
309 { 309 {
@@ -316,62 +316,62 @@ namespace Amib.Threading.Internal
316 } 316 }
317 _isDisposed = true; 317 _isDisposed = true;
318 } 318 }
319 319
320 private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType) 320 private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
321 { 321 {
322 return _pcs[(int) spcType]; 322 return _pcs[(int) spcType];
323 } 323 }
324 324
325 public void SampleThreads(long activeThreads, long inUseThreads) 325 public void SampleThreads(long activeThreads, long inUseThreads)
326 { 326 {
327 GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads); 327 GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
328 GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads); 328 GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
329 GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads); 329 GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
330 330
331 GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads); 331 GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
332 GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads); 332 GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
333 } 333 }
334 334
335 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) 335 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
336 { 336 {
337 GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed); 337 GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
338 GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued); 338 GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
339 GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed); 339 GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
340 340
341 GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued); 341 GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
342 GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed); 342 GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
343 } 343 }
344 344
345 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) 345 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
346 { 346 {
347 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds); 347 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
348 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment(); 348 GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
349 } 349 }
350 350
351 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) 351 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
352 { 352 {
353 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds); 353 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
354 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment(); 354 GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
355 } 355 }
356 } 356 }
357#endif 357#endif
358 358
359 internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader 359 internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
360 { 360 {
361 private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(); 361 private static readonly NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters();
362 362
363 public static NullSTPInstancePerformanceCounters Instance 363 public static NullSTPInstancePerformanceCounters Instance
364 { 364 {
365 get { return _instance; } 365 get { return _instance; }
366 } 366 }
367 367
368 public void Close() {} 368 public void Close() {}
369 public void Dispose() {} 369 public void Dispose() {}
370 370
371 public void SampleThreads(long activeThreads, long inUseThreads) {} 371 public void SampleThreads(long activeThreads, long inUseThreads) {}
372 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {} 372 public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
373 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {} 373 public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
374 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {} 374 public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
375 public long InUseThreads 375 public long InUseThreads
376 { 376 {
377 get { return 0; } 377 get { return 0; }
@@ -391,7 +391,7 @@ namespace Amib.Threading.Internal
391 { 391 {
392 get { return 0; } 392 get { return 0; }
393 } 393 }
394 } 394 }
395 395
396 internal class LocalSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader 396 internal class LocalSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, ISTPPerformanceCountersReader
397 { 397 {
diff --git a/ThirdParty/SmartThreadPool/STPStartInfo.cs b/ThirdParty/SmartThreadPool/STPStartInfo.cs
index 96fa094..8ea547c 100644
--- a/ThirdParty/SmartThreadPool/STPStartInfo.cs
+++ b/ThirdParty/SmartThreadPool/STPStartInfo.cs
@@ -3,9 +3,9 @@ using System.Threading;
3 3
4namespace Amib.Threading 4namespace Amib.Threading
5{ 5{
6 /// <summary> 6 /// <summary>
7 /// Summary description for STPStartInfo. 7 /// Summary description for STPStartInfo.
8 /// </summary> 8 /// </summary>
9 public class STPStartInfo : WIGStartInfo 9 public class STPStartInfo : WIGStartInfo
10 { 10 {
11 private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout; 11 private int _idleTimeout = SmartThreadPool.DefaultIdleTimeout;
@@ -31,7 +31,7 @@ namespace Amib.Threading
31 _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads; 31 _minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
32 } 32 }
33 33
34 public STPStartInfo(STPStartInfo stpStartInfo) 34 public STPStartInfo(STPStartInfo stpStartInfo)
35 : base(stpStartInfo) 35 : base(stpStartInfo)
36 { 36 {
37 _idleTimeout = stpStartInfo.IdleTimeout; 37 _idleTimeout = stpStartInfo.IdleTimeout;
@@ -48,63 +48,63 @@ namespace Amib.Threading
48 _apartmentState = stpStartInfo._apartmentState; 48 _apartmentState = stpStartInfo._apartmentState;
49#endif 49#endif
50 } 50 }
51 51
52 /// <summary> 52 /// <summary>
53 /// Get/Set the idle timeout in milliseconds. 53 /// Get/Set the idle timeout in milliseconds.
54 /// If a thread is idle (starved) longer than IdleTimeout then it may quit. 54 /// If a thread is idle (starved) longer than IdleTimeout then it may quit.
55 /// </summary> 55 /// </summary>
56 public virtual int IdleTimeout 56 public virtual int IdleTimeout
57 { 57 {
58 get { return _idleTimeout; } 58 get { return _idleTimeout; }
59 set 59 set
60 { 60 {
61 ThrowIfReadOnly(); 61 ThrowIfReadOnly();
62 _idleTimeout = value; 62 _idleTimeout = value;
63 } 63 }
64 } 64 }
65 65
66 66
67 /// <summary> 67 /// <summary>
68 /// Get/Set the lower limit of threads in the pool. 68 /// Get/Set the lower limit of threads in the pool.
69 /// </summary> 69 /// </summary>
70 public virtual int MinWorkerThreads 70 public virtual int MinWorkerThreads
71 { 71 {
72 get { return _minWorkerThreads; } 72 get { return _minWorkerThreads; }
73 set 73 set
74 { 74 {
75 ThrowIfReadOnly(); 75 ThrowIfReadOnly();
76 _minWorkerThreads = value; 76 _minWorkerThreads = value;
77 } 77 }
78 } 78 }
79 79
80 80
81 /// <summary> 81 /// <summary>
82 /// Get/Set the upper limit of threads in the pool. 82 /// Get/Set the upper limit of threads in the pool.
83 /// </summary> 83 /// </summary>
84 public virtual int MaxWorkerThreads 84 public virtual int MaxWorkerThreads
85 { 85 {
86 get { return _maxWorkerThreads; } 86 get { return _maxWorkerThreads; }
87 set 87 set
88 { 88 {
89 ThrowIfReadOnly(); 89 ThrowIfReadOnly();
90 _maxWorkerThreads = value; 90 _maxWorkerThreads = value;
91 } 91 }
92 } 92 }
93 93
94#if !(WINDOWS_PHONE) 94#if !(WINDOWS_PHONE)
95 /// <summary> 95 /// <summary>
96 /// Get/Set the scheduling priority of the threads in the pool. 96 /// Get/Set the scheduling priority of the threads in the pool.
97 /// The Os handles the scheduling. 97 /// The Os handles the scheduling.
98 /// </summary> 98 /// </summary>
99 public virtual ThreadPriority ThreadPriority 99 public virtual ThreadPriority ThreadPriority
100 { 100 {
101 get { return _threadPriority; } 101 get { return _threadPriority; }
102 set 102 set
103 { 103 {
104 ThrowIfReadOnly(); 104 ThrowIfReadOnly();
105 _threadPriority = value; 105 _threadPriority = value;
106 } 106 }
107 } 107 }
108#endif 108#endif
109 /// <summary> 109 /// <summary>
110 /// Get/Set the thread pool name. Threads will get names depending on this. 110 /// Get/Set the thread pool name. Threads will get names depending on this.
@@ -118,50 +118,50 @@ namespace Amib.Threading
118 } 118 }
119 } 119 }
120 120
121 /// <summary> 121 /// <summary>
122 /// Get/Set the performance counter instance name of this SmartThreadPool 122 /// Get/Set the performance counter instance name of this SmartThreadPool
123 /// The default is null which indicate not to use performance counters at all. 123 /// The default is null which indicate not to use performance counters at all.
124 /// </summary> 124 /// </summary>
125 public virtual string PerformanceCounterInstanceName 125 public virtual string PerformanceCounterInstanceName
126 { 126 {
127 get { return _performanceCounterInstanceName; } 127 get { return _performanceCounterInstanceName; }
128 set 128 set
129 { 129 {
130 ThrowIfReadOnly(); 130 ThrowIfReadOnly();
131 _performanceCounterInstanceName = value; 131 _performanceCounterInstanceName = value;
132 } 132 }
133 } 133 }
134 134
135 /// <summary> 135 /// <summary>
136 /// Enable/Disable the local performance counter. 136 /// Enable/Disable the local performance counter.
137 /// This enables the user to get some performance information about the SmartThreadPool 137 /// This enables the user to get some performance information about the SmartThreadPool
138 /// without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.) 138 /// without using Windows performance counters. (Useful on WindowsCE, Silverlight, etc.)
139 /// The default is false. 139 /// The default is false.
140 /// </summary> 140 /// </summary>
141 public virtual bool EnableLocalPerformanceCounters 141 public virtual bool EnableLocalPerformanceCounters
142 { 142 {
143 get { return _enableLocalPerformanceCounters; } 143 get { return _enableLocalPerformanceCounters; }
144 set 144 set
145 { 145 {
146 ThrowIfReadOnly(); 146 ThrowIfReadOnly();
147 _enableLocalPerformanceCounters = value; 147 _enableLocalPerformanceCounters = value;
148 } 148 }
149 } 149 }
150 150
151 /// <summary> 151 /// <summary>
152 /// Get/Set backgroundness of thread in thread pool. 152 /// Get/Set backgroundness of thread in thread pool.
153 /// </summary> 153 /// </summary>
154 public virtual bool AreThreadsBackground 154 public virtual bool AreThreadsBackground
155 { 155 {
156 get { return _areThreadsBackground; } 156 get { return _areThreadsBackground; }
157 set 157 set
158 { 158 {
159 ThrowIfReadOnly (); 159 ThrowIfReadOnly ();
160 _areThreadsBackground = value; 160 _areThreadsBackground = value;
161 } 161 }
162 } 162 }
163 163
164 /// <summary> 164 /// <summary>
165 /// Get a readonly version of this STPStartInfo. 165 /// Get a readonly version of this STPStartInfo.
166 /// </summary> 166 /// </summary>
167 /// <returns>Returns a readonly reference to this STPStartInfo</returns> 167 /// <returns>Returns a readonly reference to this STPStartInfo</returns>
@@ -185,10 +185,10 @@ namespace Amib.Threading
185 ThrowIfReadOnly(); 185 ThrowIfReadOnly();
186 _apartmentState = value; 186 _apartmentState = value;
187 } 187 }
188 } 188 }
189 189
190#if !(_SILVERLIGHT) && !(WINDOWS_PHONE) 190#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
191 191
192 /// <summary> 192 /// <summary>
193 /// Get/Set the max stack size of threads in the thread pool 193 /// Get/Set the max stack size of threads in the thread pool
194 /// </summary> 194 /// </summary>
diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.ThreadEntry.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.ThreadEntry.cs
index d9502bb..4713332 100644
--- a/ThirdParty/SmartThreadPool/SmartThreadPool.ThreadEntry.cs
+++ b/ThirdParty/SmartThreadPool/SmartThreadPool.ThreadEntry.cs
@@ -26,15 +26,15 @@ namespace Amib.Threading
26 /// <summary> 26 /// <summary>
27 /// A reference from each thread in the thread pool to its SmartThreadPool 27 /// A reference from each thread in the thread pool to its SmartThreadPool
28 /// object container. 28 /// object container.
29 /// With this variable a thread can know whatever it belongs to a 29 /// With this variable a thread can know whatever it belongs to a
30 /// SmartThreadPool. 30 /// SmartThreadPool.
31 /// </summary> 31 /// </summary>
32 private readonly SmartThreadPool _associatedSmartThreadPool; 32 private readonly SmartThreadPool _associatedSmartThreadPool;
33 33
34 /// <summary> 34 /// <summary>
35 /// A reference to the current work item a thread from the thread pool 35 /// A reference to the current work item a thread from the thread pool
36 /// is executing. 36 /// is executing.
37 /// </summary> 37 /// </summary>
38 public WorkItem CurrentWorkItem { get; set; } 38 public WorkItem CurrentWorkItem { get; set; }
39 39
40 public ThreadEntry(SmartThreadPool stp) 40 public ThreadEntry(SmartThreadPool stp)
diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
index 615518e..7cc7fbf 100644
--- a/ThirdParty/SmartThreadPool/SmartThreadPool.cs
+++ b/ThirdParty/SmartThreadPool/SmartThreadPool.cs
@@ -3,7 +3,7 @@
3// Smart Thread Pool 3// Smart Thread Pool
4// 7 Aug 2004 - Initial release 4// 7 Aug 2004 - Initial release
5// 5//
6// 14 Sep 2004 - Bug fixes 6// 14 Sep 2004 - Bug fixes
7// 7//
8// 15 Oct 2004 - Added new features 8// 15 Oct 2004 - Added new features
9// - Work items return result. 9// - Work items return result.
@@ -18,13 +18,13 @@
18// - Added finalizers. 18// - Added finalizers.
19// - Changed Exceptions so they are serializable. 19// - Changed Exceptions so they are serializable.
20// - Fixed the bug in one of the SmartThreadPool constructors. 20// - Fixed the bug in one of the SmartThreadPool constructors.
21// - Changed the SmartThreadPool.WaitAll() so it will support any number of waiters. 21// - Changed the SmartThreadPool.WaitAll() so it will support any number of waiters.
22// The SmartThreadPool.WaitAny() is still limited by the .NET Framework. 22// The SmartThreadPool.WaitAny() is still limited by the .NET Framework.
23// - Added PostExecute with options on which cases to call it. 23// - Added PostExecute with options on which cases to call it.
24// - Added option to dispose of the state objects. 24// - Added option to dispose of the state objects.
25// - Added a WaitForIdle() method that waits until the work items queue is empty. 25// - Added a WaitForIdle() method that waits until the work items queue is empty.
26// - Added an STPStartInfo class for the initialization of the thread pool. 26// - Added an STPStartInfo class for the initialization of the thread pool.
27// - Changed exception handling so if a work item throws an exception it 27// - Changed exception handling so if a work item throws an exception it
28// is rethrown at GetResult(), rather then firing an UnhandledException event. 28// is rethrown at GetResult(), rather then firing an UnhandledException event.
29// Note that PostExecute exception are always ignored. 29// Note that PostExecute exception are always ignored.
30// 30//
@@ -32,10 +32,10 @@
32// - Fixed lost of work items bug 32// - Fixed lost of work items bug
33// 33//
34// 3 Jul 2005: Changes. 34// 3 Jul 2005: Changes.
35// - Fixed bug where Enqueue() throws an exception because PopWaiter() returned null, hardly reconstructed. 35// - Fixed bug where Enqueue() throws an exception because PopWaiter() returned null, hardly reconstructed.
36// 36//
37// 16 Aug 2005: Changes. 37// 16 Aug 2005: Changes.
38// - Fixed bug where the InUseThreads becomes negative when canceling work items. 38// - Fixed bug where the InUseThreads becomes negative when canceling work items.
39// 39//
40// 31 Jan 2006 - Changes: 40// 31 Jan 2006 - Changes:
41// - Added work items priority 41// - Added work items priority
@@ -45,7 +45,7 @@
45// - Changed SmartThreadPool.WaitAll() behavior so when it gets empty array 45// - Changed SmartThreadPool.WaitAll() behavior so when it gets empty array
46// it returns true rather then throwing an exception. 46// it returns true rather then throwing an exception.
47// - Added option to start the STP and the WIG as suspended 47// - Added option to start the STP and the WIG as suspended
48// - Exception behavior changed, the real exception is returned by an 48// - Exception behavior changed, the real exception is returned by an
49// inner exception 49// inner exception
50// - Added option to keep the Http context of the caller thread. (Thanks to Steven T.) 50// - Added option to keep the Http context of the caller thread. (Thanks to Steven T.)
51// - Added performance counters 51// - Added performance counters
@@ -54,17 +54,17 @@
54// 13 Feb 2006 - Changes: 54// 13 Feb 2006 - Changes:
55// - Added a call to the dispose of the Performance Counter so 55// - Added a call to the dispose of the Performance Counter so
56// their won't be a Performance Counter leak. 56// their won't be a Performance Counter leak.
57// - Added exception catch in case the Performance Counters cannot 57// - Added exception catch in case the Performance Counters cannot
58// be created. 58// be created.
59// 59//
60// 17 May 2008 - Changes: 60// 17 May 2008 - Changes:
61// - Changed the dispose behavior and removed the Finalizers. 61// - Changed the dispose behavior and removed the Finalizers.
62// - Enabled the change of the MaxThreads and MinThreads at run time. 62// - Enabled the change of the MaxThreads and MinThreads at run time.
63// - Enabled the change of the Concurrency of a IWorkItemsGroup at run 63// - Enabled the change of the Concurrency of a IWorkItemsGroup at run
64// time If the IWorkItemsGroup is a SmartThreadPool then the Concurrency 64// time If the IWorkItemsGroup is a SmartThreadPool then the Concurrency
65// refers to the MaxThreads. 65// refers to the MaxThreads.
66// - Improved the cancel behavior. 66// - Improved the cancel behavior.
67// - Added events for thread creation and termination. 67// - Added events for thread creation and termination.
68// - Fixed the HttpContext context capture. 68// - Fixed the HttpContext context capture.
69// - Changed internal collections so they use generic collections 69// - Changed internal collections so they use generic collections
70// - Added IsIdle flag to the SmartThreadPool and IWorkItemsGroup 70// - Added IsIdle flag to the SmartThreadPool and IWorkItemsGroup
@@ -83,7 +83,7 @@
83// 83//
84// 20 August 2012 - Changes: 84// 20 August 2012 - Changes:
85// - Added set name to threads 85// - Added set name to threads
86// - Fixed the WorkItemsQueue.Dequeue. 86// - Fixed the WorkItemsQueue.Dequeue.
87// Replaced while (!Monitor.TryEnter(this)); with lock(this) { ... } 87// Replaced while (!Monitor.TryEnter(this)); with lock(this) { ... }
88// - Fixed SmartThreadPool.Pipe 88// - Fixed SmartThreadPool.Pipe
89// - Added IsBackground option to threads 89// - Added IsBackground option to threads
@@ -92,7 +92,7 @@
92// 92//
93// 24 August 2012 - Changes: 93// 24 August 2012 - Changes:
94// - Enabled cancel abort after cancel. See: http://smartthreadpool.codeplex.com/discussions/345937 by alecswan 94// - Enabled cancel abort after cancel. See: http://smartthreadpool.codeplex.com/discussions/345937 by alecswan
95// - Added option to set MaxStackSize of threads 95// - Added option to set MaxStackSize of threads
96 96
97#endregion 97#endregion
98 98
@@ -108,77 +108,77 @@ using Amib.Threading.Internal;
108 108
109namespace Amib.Threading 109namespace Amib.Threading
110{ 110{
111 #region SmartThreadPool class 111 #region SmartThreadPool class
112 /// <summary> 112 /// <summary>
113 /// Smart thread pool class. 113 /// Smart thread pool class.
114 /// </summary> 114 /// </summary>
115 public partial class SmartThreadPool : WorkItemsGroupBase, IDisposable 115 public partial class SmartThreadPool : WorkItemsGroupBase, IDisposable
116 { 116 {
117 #region Public Default Constants 117 #region Public Default Constants
118 118
119 /// <summary> 119 /// <summary>
120 /// Default minimum number of threads the thread pool contains. (0) 120 /// Default minimum number of threads the thread pool contains. (0)
121 /// </summary> 121 /// </summary>
122 public const int DefaultMinWorkerThreads = 0; 122 public const int DefaultMinWorkerThreads = 0;
123 123
124 /// <summary> 124 /// <summary>
125 /// Default maximum number of threads the thread pool contains. (25) 125 /// Default maximum number of threads the thread pool contains. (25)
126 /// </summary> 126 /// </summary>
127 public const int DefaultMaxWorkerThreads = 25; 127 public const int DefaultMaxWorkerThreads = 25;
128 128
129 /// <summary> 129 /// <summary>
130 /// Default idle timeout in milliseconds. (One minute) 130 /// Default idle timeout in milliseconds. (One minute)
131 /// </summary> 131 /// </summary>
132 public const int DefaultIdleTimeout = 60*1000; // One minute 132 public const int DefaultIdleTimeout = 60*1000; // One minute
133 133
134 /// <summary> 134 /// <summary>
135 /// Indicate to copy the security context of the caller and then use it in the call. (false) 135 /// Indicate to copy the security context of the caller and then use it in the call. (false)
136 /// </summary> 136 /// </summary>
137 public const bool DefaultUseCallerCallContext = false; 137 public const bool DefaultUseCallerCallContext = false;
138 138
139 /// <summary> 139 /// <summary>
140 /// Indicate to copy the HTTP context of the caller and then use it in the call. (false) 140 /// Indicate to copy the HTTP context of the caller and then use it in the call. (false)
141 /// </summary> 141 /// </summary>
142 public const bool DefaultUseCallerHttpContext = false; 142 public const bool DefaultUseCallerHttpContext = false;
143 143
144 /// <summary> 144 /// <summary>
145 /// Indicate to dispose of the state objects if they support the IDispose interface. (false) 145 /// Indicate to dispose of the state objects if they support the IDispose interface. (false)
146 /// </summary> 146 /// </summary>
147 public const bool DefaultDisposeOfStateObjects = false; 147 public const bool DefaultDisposeOfStateObjects = false;
148 148
149 /// <summary> 149 /// <summary>
150 /// The default option to run the post execute (CallToPostExecute.Always) 150 /// The default option to run the post execute (CallToPostExecute.Always)
151 /// </summary> 151 /// </summary>
152 public const CallToPostExecute DefaultCallToPostExecute = CallToPostExecute.Always; 152 public const CallToPostExecute DefaultCallToPostExecute = CallToPostExecute.Always;
153 153
154 /// <summary> 154 /// <summary>
155 /// The default post execute method to run. (None) 155 /// The default post execute method to run. (None)
156 /// When null it means not to call it. 156 /// When null it means not to call it.
157 /// </summary> 157 /// </summary>
158 public static readonly PostExecuteWorkItemCallback DefaultPostExecuteWorkItemCallback; 158 public static readonly PostExecuteWorkItemCallback DefaultPostExecuteWorkItemCallback;
159 159
160 /// <summary> 160 /// <summary>
161 /// The default work item priority (WorkItemPriority.Normal) 161 /// The default work item priority (WorkItemPriority.Normal)
162 /// </summary> 162 /// </summary>
163 public const WorkItemPriority DefaultWorkItemPriority = WorkItemPriority.Normal; 163 public const WorkItemPriority DefaultWorkItemPriority = WorkItemPriority.Normal;
164 164
165 /// <summary> 165 /// <summary>
166 /// The default is to work on work items as soon as they arrive 166 /// The default is to work on work items as soon as they arrive
167 /// and not to wait for the start. (false) 167 /// and not to wait for the start. (false)
168 /// </summary> 168 /// </summary>
169 public const bool DefaultStartSuspended = false; 169 public const bool DefaultStartSuspended = false;
170 170
171 /// <summary> 171 /// <summary>
172 /// The default name to use for the performance counters instance. (null) 172 /// The default name to use for the performance counters instance. (null)
173 /// </summary> 173 /// </summary>
174 public static readonly string DefaultPerformanceCounterInstanceName; 174 public static readonly string DefaultPerformanceCounterInstanceName;
175 175
176#if !(WINDOWS_PHONE) 176#if !(WINDOWS_PHONE)
177 177
178 /// <summary> 178 /// <summary>
179 /// The default thread priority (ThreadPriority.Normal) 179 /// The default thread priority (ThreadPriority.Normal)
180 /// </summary> 180 /// </summary>
181 public const ThreadPriority DefaultThreadPriority = ThreadPriority.Normal; 181 public const ThreadPriority DefaultThreadPriority = ThreadPriority.Normal;
182#endif 182#endif
183 /// <summary> 183 /// <summary>
184 /// The default thread pool name. (SmartThreadPool) 184 /// The default thread pool name. (SmartThreadPool)
@@ -203,37 +203,37 @@ namespace Amib.Threading
203 203
204#if !(_SILVERLIGHT) && !(WINDOWS_PHONE) 204#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
205 /// <summary> 205 /// <summary>
206 /// The default apartment state of a thread in the thread pool. 206 /// The default apartment state of a thread in the thread pool.
207 /// The default is ApartmentState.Unknown which means the STP will not 207 /// The default is ApartmentState.Unknown which means the STP will not
208 /// set the apartment of the thread. It will use the .NET default. 208 /// set the apartment of the thread. It will use the .NET default.
209 /// </summary> 209 /// </summary>
210 public const ApartmentState DefaultApartmentState = ApartmentState.Unknown; 210 public const ApartmentState DefaultApartmentState = ApartmentState.Unknown;
211#endif 211#endif
212 212
213 #endregion 213 #endregion
214 214
215 #region Member Variables 215 #region Member Variables
216 216
217 /// <summary> 217 /// <summary>
218 /// Dictionary of all the threads in the thread pool. 218 /// Dictionary of all the threads in the thread pool.
219 /// </summary> 219 /// </summary>
220 private readonly SynchronizedDictionary<Thread, ThreadEntry> _workerThreads = new SynchronizedDictionary<Thread, ThreadEntry>(); 220 private readonly SynchronizedDictionary<Thread, ThreadEntry> _workerThreads = new SynchronizedDictionary<Thread, ThreadEntry>();
221 221
222 /// <summary> 222 /// <summary>
223 /// Queue of work items. 223 /// Queue of work items.
224 /// </summary> 224 /// </summary>
225 private readonly WorkItemsQueue _workItemsQueue = new WorkItemsQueue(); 225 private readonly WorkItemsQueue _workItemsQueue = new WorkItemsQueue();
226 226
227 /// <summary> 227 /// <summary>
228 /// Count the work items handled. 228 /// Count the work items handled.
229 /// Used by the performance counter. 229 /// Used by the performance counter.
230 /// </summary> 230 /// </summary>
231 private int _workItemsProcessed; 231 private int _workItemsProcessed;
232 232
233 /// <summary> 233 /// <summary>
234 /// Number of threads that currently work (not idle). 234 /// Number of threads that currently work (not idle).
235 /// </summary> 235 /// </summary>
236 private int _inUseWorkerThreads; 236 private int _inUseWorkerThreads;
237 237
238 /// <summary> 238 /// <summary>
239 /// Stores a copy of the original STPStartInfo. 239 /// Stores a copy of the original STPStartInfo.
@@ -241,51 +241,51 @@ namespace Amib.Threading
241 /// </summary> 241 /// </summary>
242 private STPStartInfo _stpStartInfo; 242 private STPStartInfo _stpStartInfo;
243 243
244 /// <summary> 244 /// <summary>
245 /// Total number of work items that are stored in the work items queue 245 /// Total number of work items that are stored in the work items queue
246 /// plus the work items that the threads in the pool are working on. 246 /// plus the work items that the threads in the pool are working on.
247 /// </summary> 247 /// </summary>
248 private int _currentWorkItemsCount; 248 private int _currentWorkItemsCount;
249 249
250 /// <summary> 250 /// <summary>
251 /// Signaled when the thread pool is idle, i.e. no thread is busy 251 /// Signaled when the thread pool is idle, i.e. no thread is busy
252 /// and the work items queue is empty 252 /// and the work items queue is empty
253 /// </summary> 253 /// </summary>
254 //private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true); 254 //private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
255 private ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true); 255 private ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true);
256 256
257 /// <summary> 257 /// <summary>
258 /// An event to signal all the threads to quit immediately. 258 /// An event to signal all the threads to quit immediately.
259 /// </summary> 259 /// </summary>
260 //private ManualResetEvent _shuttingDownEvent = new ManualResetEvent(false); 260 //private ManualResetEvent _shuttingDownEvent = new ManualResetEvent(false);
261 private ManualResetEvent _shuttingDownEvent = EventWaitHandleFactory.CreateManualResetEvent(false); 261 private ManualResetEvent _shuttingDownEvent = EventWaitHandleFactory.CreateManualResetEvent(false);
262 262
263 /// <summary> 263 /// <summary>
264 /// A flag to indicate if the Smart Thread Pool is now suspended. 264 /// A flag to indicate if the Smart Thread Pool is now suspended.
265 /// </summary> 265 /// </summary>
266 private bool _isSuspended; 266 private bool _isSuspended;
267 267
268 /// <summary> 268 /// <summary>
269 /// A flag to indicate the threads to quit. 269 /// A flag to indicate the threads to quit.
270 /// </summary> 270 /// </summary>
271 private bool _shutdown; 271 private bool _shutdown;
272 272
273 /// <summary> 273 /// <summary>
274 /// Counts the threads created in the pool. 274 /// Counts the threads created in the pool.
275 /// It is used to name the threads. 275 /// It is used to name the threads.
276 /// </summary> 276 /// </summary>
277 private int _threadCounter; 277 private int _threadCounter;
278 278
279 /// <summary> 279 /// <summary>
280 /// Indicate that the SmartThreadPool has been disposed 280 /// Indicate that the SmartThreadPool has been disposed
281 /// </summary> 281 /// </summary>
282 private bool _isDisposed; 282 private bool _isDisposed;
283 283
284 /// <summary> 284 /// <summary>
285 /// Holds all the WorkItemsGroup instaces that have at least one 285 /// Holds all the WorkItemsGroup instaces that have at least one
286 /// work item int the SmartThreadPool 286 /// work item int the SmartThreadPool
287 /// This variable is used in case of Shutdown 287 /// This variable is used in case of Shutdown
288 /// </summary> 288 /// </summary>
289 private readonly SynchronizedDictionary<IWorkItemsGroup, IWorkItemsGroup> _workItemsGroups = new SynchronizedDictionary<IWorkItemsGroup, IWorkItemsGroup>(); 289 private readonly SynchronizedDictionary<IWorkItemsGroup, IWorkItemsGroup> _workItemsGroups = new SynchronizedDictionary<IWorkItemsGroup, IWorkItemsGroup>();
290 290
291 /// <summary> 291 /// <summary>
@@ -305,7 +305,7 @@ namespace Amib.Threading
305 private ISTPInstancePerformanceCounters _localPCs = NullSTPInstancePerformanceCounters.Instance; 305 private ISTPInstancePerformanceCounters _localPCs = NullSTPInstancePerformanceCounters.Instance;
306 306
307 307
308#if (WINDOWS_PHONE) 308#if (WINDOWS_PHONE)
309 private static readonly Dictionary<int, ThreadEntry> _threadEntries = new Dictionary<int, ThreadEntry>(); 309 private static readonly Dictionary<int, ThreadEntry> _threadEntries = new Dictionary<int, ThreadEntry>();
310#elif (_WINDOWS_CE) 310#elif (_WINDOWS_CE)
311 private static LocalDataStoreSlot _threadEntrySlot = Thread.AllocateDataSlot(); 311 private static LocalDataStoreSlot _threadEntrySlot = Thread.AllocateDataSlot();
@@ -316,13 +316,13 @@ namespace Amib.Threading
316#endif 316#endif
317 317
318 /// <summary> 318 /// <summary>
319 /// An event to call after a thread is created, but before 319 /// An event to call after a thread is created, but before
320 /// it's first use. 320 /// it's first use.
321 /// </summary> 321 /// </summary>
322 private event ThreadInitializationHandler _onThreadInitialization; 322 private event ThreadInitializationHandler _onThreadInitialization;
323 323
324 /// <summary> 324 /// <summary>
325 /// An event to call when a thread is about to exit, after 325 /// An event to call when a thread is about to exit, after
326 /// it is no longer belong to the pool. 326 /// it is no longer belong to the pool.
327 /// </summary> 327 /// </summary>
328 private event ThreadTerminationHandler _onThreadTermination; 328 private event ThreadTerminationHandler _onThreadTermination;
@@ -332,7 +332,7 @@ namespace Amib.Threading
332 #region Per thread properties 332 #region Per thread properties
333 333
334 /// <summary> 334 /// <summary>
335 /// A reference to the current work item a thread from the thread pool 335 /// A reference to the current work item a thread from the thread pool
336 /// is executing. 336 /// is executing.
337 /// </summary> 337 /// </summary>
338 internal static ThreadEntry CurrentThreadEntry 338 internal static ThreadEntry CurrentThreadEntry
@@ -383,78 +383,78 @@ namespace Amib.Threading
383 #region Construction and Finalization 383 #region Construction and Finalization
384 384
385 /// <summary> 385 /// <summary>
386 /// Constructor 386 /// Constructor
387 /// </summary> 387 /// </summary>
388 public SmartThreadPool() 388 public SmartThreadPool()
389 { 389 {
390 _stpStartInfo = new STPStartInfo(); 390 _stpStartInfo = new STPStartInfo();
391 Initialize(); 391 Initialize();
392 } 392 }
393 393
394 /// <summary> 394 /// <summary>
395 /// Constructor 395 /// Constructor
396 /// </summary> 396 /// </summary>
397 /// <param name="idleTimeout">Idle timeout in milliseconds</param> 397 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
398 public SmartThreadPool(int idleTimeout) 398 public SmartThreadPool(int idleTimeout)
399 { 399 {
400 _stpStartInfo = new STPStartInfo 400 _stpStartInfo = new STPStartInfo
401 { 401 {
402 IdleTimeout = idleTimeout, 402 IdleTimeout = idleTimeout,
403 }; 403 };
404 Initialize(); 404 Initialize();
405 } 405 }
406 406
407 /// <summary> 407 /// <summary>
408 /// Constructor 408 /// Constructor
409 /// </summary> 409 /// </summary>
410 /// <param name="idleTimeout">Idle timeout in milliseconds</param> 410 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
411 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param> 411 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
412 public SmartThreadPool( 412 public SmartThreadPool(
413 int idleTimeout, 413 int idleTimeout,
414 int maxWorkerThreads) 414 int maxWorkerThreads)
415 { 415 {
416 _stpStartInfo = new STPStartInfo 416 _stpStartInfo = new STPStartInfo
417 { 417 {
418 IdleTimeout = idleTimeout, 418 IdleTimeout = idleTimeout,
419 MaxWorkerThreads = maxWorkerThreads, 419 MaxWorkerThreads = maxWorkerThreads,
420 }; 420 };
421 Initialize(); 421 Initialize();
422 } 422 }
423 423
424 /// <summary> 424 /// <summary>
425 /// Constructor 425 /// Constructor
426 /// </summary> 426 /// </summary>
427 /// <param name="idleTimeout">Idle timeout in milliseconds</param> 427 /// <param name="idleTimeout">Idle timeout in milliseconds</param>
428 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param> 428 /// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
429 /// <param name="minWorkerThreads">Lower limit of threads in the pool</param> 429 /// <param name="minWorkerThreads">Lower limit of threads in the pool</param>
430 public SmartThreadPool( 430 public SmartThreadPool(
431 int idleTimeout, 431 int idleTimeout,
432 int maxWorkerThreads, 432 int maxWorkerThreads,
433 int minWorkerThreads) 433 int minWorkerThreads)
434 { 434 {
435 _stpStartInfo = new STPStartInfo 435 _stpStartInfo = new STPStartInfo
436 { 436 {
437 IdleTimeout = idleTimeout, 437 IdleTimeout = idleTimeout,
438 MaxWorkerThreads = maxWorkerThreads, 438 MaxWorkerThreads = maxWorkerThreads,
439 MinWorkerThreads = minWorkerThreads, 439 MinWorkerThreads = minWorkerThreads,
440 }; 440 };
441 Initialize(); 441 Initialize();
442 } 442 }
443 443
444 /// <summary> 444 /// <summary>
445 /// Constructor 445 /// Constructor
446 /// </summary> 446 /// </summary>
447 /// <param name="stpStartInfo">A SmartThreadPool configuration that overrides the default behavior</param> 447 /// <param name="stpStartInfo">A SmartThreadPool configuration that overrides the default behavior</param>
448 public SmartThreadPool(STPStartInfo stpStartInfo) 448 public SmartThreadPool(STPStartInfo stpStartInfo)
449 { 449 {
450 _stpStartInfo = new STPStartInfo(stpStartInfo); 450 _stpStartInfo = new STPStartInfo(stpStartInfo);
451 Initialize(); 451 Initialize();
452 } 452 }
453 453
454 private void Initialize() 454 private void Initialize()
455 { 455 {
456 Name = _stpStartInfo.ThreadPoolName; 456 Name = _stpStartInfo.ThreadPoolName;
457 ValidateSTPStartInfo(); 457 ValidateSTPStartInfo();
458 458
459 // _stpStartInfoRW stores a read/write copy of the STPStartInfo. 459 // _stpStartInfoRW stores a read/write copy of the STPStartInfo.
460 // Actually only MaxWorkerThreads and MinWorkerThreads are overwritten 460 // Actually only MaxWorkerThreads and MinWorkerThreads are overwritten
@@ -462,8 +462,8 @@ namespace Amib.Threading
462 _isSuspended = _stpStartInfo.StartSuspended; 462 _isSuspended = _stpStartInfo.StartSuspended;
463 463
464#if (_WINDOWS_CE) || (_SILVERLIGHT) || (_MONO) || (WINDOWS_PHONE) 464#if (_WINDOWS_CE) || (_SILVERLIGHT) || (_MONO) || (WINDOWS_PHONE)
465 if (null != _stpStartInfo.PerformanceCounterInstanceName) 465 if (null != _stpStartInfo.PerformanceCounterInstanceName)
466 { 466 {
467 throw new NotSupportedException("Performance counters are not implemented for Compact Framework/Silverlight/Mono, instead use StpStartInfo.EnableLocalPerformanceCounters"); 467 throw new NotSupportedException("Performance counters are not implemented for Compact Framework/Silverlight/Mono, instead use StpStartInfo.EnableLocalPerformanceCounters");
468 } 468 }
469#else 469#else
@@ -486,110 +486,110 @@ namespace Amib.Threading
486 _localPCs = new LocalSTPInstancePerformanceCounters(); 486 _localPCs = new LocalSTPInstancePerformanceCounters();
487 } 487 }
488 488
489 // If the STP is not started suspended then start the threads. 489 // If the STP is not started suspended then start the threads.
490 if (!_isSuspended) 490 if (!_isSuspended)
491 { 491 {
492 StartOptimalNumberOfThreads(); 492 StartOptimalNumberOfThreads();
493 } 493 }
494 } 494 }
495 495
496 private void StartOptimalNumberOfThreads() 496 private void StartOptimalNumberOfThreads()
497 { 497 {
498 int threadsCount = Math.Max(_workItemsQueue.Count, _stpStartInfo.MinWorkerThreads); 498 int threadsCount = Math.Max(_workItemsQueue.Count, _stpStartInfo.MinWorkerThreads);
499 threadsCount = Math.Min(threadsCount, _stpStartInfo.MaxWorkerThreads); 499 threadsCount = Math.Min(threadsCount, _stpStartInfo.MaxWorkerThreads);
500 threadsCount -= _workerThreads.Count; 500 threadsCount -= _workerThreads.Count;
501 if (threadsCount > 0) 501 if (threadsCount > 0)
502 { 502 {
503 StartThreads(threadsCount); 503 StartThreads(threadsCount);
504 } 504 }
505 } 505 }
506 506
507 private void ValidateSTPStartInfo() 507 private void ValidateSTPStartInfo()
508 { 508 {
509 if (_stpStartInfo.MinWorkerThreads < 0) 509 if (_stpStartInfo.MinWorkerThreads < 0)
510 { 510 {
511 throw new ArgumentOutOfRangeException( 511 throw new ArgumentOutOfRangeException(
512 "MinWorkerThreads", "MinWorkerThreads cannot be negative"); 512 "MinWorkerThreads", "MinWorkerThreads cannot be negative");
513 } 513 }
514 514
515 if (_stpStartInfo.MaxWorkerThreads <= 0) 515 if (_stpStartInfo.MaxWorkerThreads <= 0)
516 { 516 {
517 throw new ArgumentOutOfRangeException( 517 throw new ArgumentOutOfRangeException(
518 "MaxWorkerThreads", "MaxWorkerThreads must be greater than zero"); 518 "MaxWorkerThreads", "MaxWorkerThreads must be greater than zero");
519 } 519 }
520 520
521 if (_stpStartInfo.MinWorkerThreads > _stpStartInfo.MaxWorkerThreads) 521 if (_stpStartInfo.MinWorkerThreads > _stpStartInfo.MaxWorkerThreads)
522 { 522 {
523 throw new ArgumentOutOfRangeException( 523 throw new ArgumentOutOfRangeException(
524 "MinWorkerThreads, maxWorkerThreads", 524 "MinWorkerThreads, maxWorkerThreads",
525 "MaxWorkerThreads must be greater or equal to MinWorkerThreads"); 525 "MaxWorkerThreads must be greater or equal to MinWorkerThreads");
526 } 526 }
527 } 527 }
528 528
529 private static void ValidateCallback(Delegate callback) 529 private static void ValidateCallback(Delegate callback)
530 { 530 {
531 if(callback.GetInvocationList().Length > 1) 531 if(callback.GetInvocationList().Length > 1)
532 { 532 {
533 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains"); 533 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
534 } 534 }
535 } 535 }
536 536
537 #endregion 537 #endregion
538 538
539 #region Thread Processing 539 #region Thread Processing
540 540
541 /// <summary> 541 /// <summary>
542 /// Waits on the queue for a work item, shutdown, or timeout. 542 /// Waits on the queue for a work item, shutdown, or timeout.
543 /// </summary> 543 /// </summary>
544 /// <returns> 544 /// <returns>
545 /// Returns the WaitingCallback or null in case of timeout or shutdown. 545 /// Returns the WaitingCallback or null in case of timeout or shutdown.
546 /// </returns> 546 /// </returns>
547 private WorkItem Dequeue() 547 private WorkItem Dequeue()
548 { 548 {
549 WorkItem workItem = 549 WorkItem workItem =
550 _workItemsQueue.DequeueWorkItem(_stpStartInfo.IdleTimeout, _shuttingDownEvent); 550 _workItemsQueue.DequeueWorkItem(_stpStartInfo.IdleTimeout, _shuttingDownEvent);
551 551
552 return workItem; 552 return workItem;
553 } 553 }
554 554
555 /// <summary> 555 /// <summary>
556 /// Put a new work item in the queue 556 /// Put a new work item in the queue
557 /// </summary> 557 /// </summary>
558 /// <param name="workItem">A work item to queue</param> 558 /// <param name="workItem">A work item to queue</param>
559 internal override void Enqueue(WorkItem workItem) 559 internal override void Enqueue(WorkItem workItem)
560 { 560 {
561 // Make sure the workItem is not null 561 // Make sure the workItem is not null
562 Debug.Assert(null != workItem); 562 Debug.Assert(null != workItem);
563 563
564 IncrementWorkItemsCount(); 564 IncrementWorkItemsCount();
565 565
566 workItem.CanceledSmartThreadPool = _canceledSmartThreadPool; 566 workItem.CanceledSmartThreadPool = _canceledSmartThreadPool;
567 _workItemsQueue.EnqueueWorkItem(workItem); 567 _workItemsQueue.EnqueueWorkItem(workItem);
568 workItem.WorkItemIsQueued(); 568 workItem.WorkItemIsQueued();
569 569
570 // If all the threads are busy then try to create a new one 570 // If all the threads are busy then try to create a new one
571 if (_currentWorkItemsCount > _workerThreads.Count) 571 if (_currentWorkItemsCount > _workerThreads.Count)
572 { 572 {
573 StartThreads(1); 573 StartThreads(1);
574 } 574 }
575 } 575 }
576 576
577 private void IncrementWorkItemsCount() 577 private void IncrementWorkItemsCount()
578 { 578 {
579 _windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed); 579 _windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
580 _localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed); 580 _localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
581 581
582 int count = Interlocked.Increment(ref _currentWorkItemsCount); 582 int count = Interlocked.Increment(ref _currentWorkItemsCount);
583 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString()); 583 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
584 if (count == 1) 584 if (count == 1)
585 { 585 {
586 IsIdle = false; 586 IsIdle = false;
587 _isIdleWaitHandle.Reset(); 587 _isIdleWaitHandle.Reset();
588 } 588 }
589 } 589 }
590 590
591 private void DecrementWorkItemsCount() 591 private void DecrementWorkItemsCount()
592 { 592 {
593 int count = Interlocked.Decrement(ref _currentWorkItemsCount); 593 int count = Interlocked.Decrement(ref _currentWorkItemsCount);
594 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString()); 594 //Trace.WriteLine("WorkItemsCount = " + _currentWorkItemsCount.ToString());
595 if (count == 0) 595 if (count == 0)
@@ -602,81 +602,81 @@ namespace Amib.Threading
602 602
603 if (!_shutdown) 603 if (!_shutdown)
604 { 604 {
605 // The counter counts even if the work item was cancelled 605 // The counter counts even if the work item was cancelled
606 _windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed); 606 _windowsPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
607 _localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed); 607 _localPCs.SampleWorkItems(_workItemsQueue.Count, _workItemsProcessed);
608 } 608 }
609 609
610 } 610 }
611 611
612 internal void RegisterWorkItemsGroup(IWorkItemsGroup workItemsGroup) 612 internal void RegisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
613 { 613 {
614 _workItemsGroups[workItemsGroup] = workItemsGroup; 614 _workItemsGroups[workItemsGroup] = workItemsGroup;
615 } 615 }
616 616
617 internal void UnregisterWorkItemsGroup(IWorkItemsGroup workItemsGroup) 617 internal void UnregisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
618 { 618 {
619 if (_workItemsGroups.Contains(workItemsGroup)) 619 if (_workItemsGroups.Contains(workItemsGroup))
620 { 620 {
621 _workItemsGroups.Remove(workItemsGroup); 621 _workItemsGroups.Remove(workItemsGroup);
622 } 622 }
623 } 623 }
624 624
625 /// <summary> 625 /// <summary>
626 /// Inform that the current thread is about to quit or quiting. 626 /// Inform that the current thread is about to quit or quiting.
627 /// The same thread may call this method more than once. 627 /// The same thread may call this method more than once.
628 /// </summary> 628 /// </summary>
629 private void InformCompleted() 629 private void InformCompleted()
630 { 630 {
631 // There is no need to lock the two methods together 631 // There is no need to lock the two methods together
632 // since only the current thread removes itself 632 // since only the current thread removes itself
633 // and the _workerThreads is a synchronized dictionary 633 // and the _workerThreads is a synchronized dictionary
634 if (_workerThreads.Contains(Thread.CurrentThread)) 634 if (_workerThreads.Contains(Thread.CurrentThread))
635 { 635 {
636 _workerThreads.Remove(Thread.CurrentThread); 636 _workerThreads.Remove(Thread.CurrentThread);
637 _windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads); 637 _windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
638 _localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads); 638 _localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
639 } 639 }
640 } 640 }
641 641
642 /// <summary> 642 /// <summary>
643 /// Starts new threads 643 /// Starts new threads
644 /// </summary> 644 /// </summary>
645 /// <param name="threadsCount">The number of threads to start</param> 645 /// <param name="threadsCount">The number of threads to start</param>
646 private void StartThreads(int threadsCount) 646 private void StartThreads(int threadsCount)
647 { 647 {
648 if (_isSuspended) 648 if (_isSuspended)
649 { 649 {
650 return; 650 return;
651 } 651 }
652 652
653 lock(_workerThreads.SyncRoot) 653 lock(_workerThreads.SyncRoot)
654 { 654 {
655 // Don't start threads on shut down 655 // Don't start threads on shut down
656 if (_shutdown) 656 if (_shutdown)
657 { 657 {
658 return; 658 return;
659 } 659 }
660 660
661 for(int i = 0; i < threadsCount; ++i) 661 for(int i = 0; i < threadsCount; ++i)
662 { 662 {
663 // Don't create more threads then the upper limit 663 // Don't create more threads then the upper limit
664 if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads) 664 if (_workerThreads.Count >= _stpStartInfo.MaxWorkerThreads)
665 { 665 {
666 return; 666 return;
667 } 667 }
668 668
669 // Create a new thread 669 // Create a new thread
670 670
671#if (_SILVERLIGHT) || (WINDOWS_PHONE) 671#if (_SILVERLIGHT) || (WINDOWS_PHONE)
672 Thread workerThread = new Thread(ProcessQueuedItems); 672 Thread workerThread = new Thread(ProcessQueuedItems);
673#else 673#else
674 Thread workerThread = 674 Thread workerThread =
675 _stpStartInfo.MaxStackSize.HasValue 675 _stpStartInfo.MaxStackSize.HasValue
676 ? new Thread(ProcessQueuedItems, _stpStartInfo.MaxStackSize.Value) 676 ? new Thread(ProcessQueuedItems, _stpStartInfo.MaxStackSize.Value)
677 : new Thread(ProcessQueuedItems); 677 : new Thread(ProcessQueuedItems);
678#endif 678#endif
679 // Configure the new thread and start it 679 // Configure the new thread and start it
680 workerThread.IsBackground = _stpStartInfo.AreThreadsBackground; 680 workerThread.IsBackground = _stpStartInfo.AreThreadsBackground;
681 681
682#if !(_SILVERLIGHT) && !(_WINDOWS_CE) && !(WINDOWS_PHONE) 682#if !(_SILVERLIGHT) && !(_WINDOWS_CE) && !(WINDOWS_PHONE)
@@ -689,39 +689,40 @@ namespace Amib.Threading
689#if !(_SILVERLIGHT) && !(WINDOWS_PHONE) 689#if !(_SILVERLIGHT) && !(WINDOWS_PHONE)
690 workerThread.Priority = _stpStartInfo.ThreadPriority; 690 workerThread.Priority = _stpStartInfo.ThreadPriority;
691#endif 691#endif
692 workerThread.Start();
693 workerThread.Name = string.Format("STP:{0}:{1}", Name, _threadCounter); 692 workerThread.Name = string.Format("STP:{0}:{1}", Name, _threadCounter);
694 ++_threadCounter; 693 workerThread.Start();
694
695 ++_threadCounter;
695 696
696 // Add it to the dictionary and update its creation time. 697 // Add it to the dictionary and update its creation time.
697 _workerThreads[workerThread] = new ThreadEntry(this); 698 _workerThreads[workerThread] = new ThreadEntry(this);
698 699
699 _windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads); 700 _windowsPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
700 _localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads); 701 _localPCs.SampleThreads(_workerThreads.Count, _inUseWorkerThreads);
701 } 702 }
702 } 703 }
703 } 704 }
704 705
705 /// <summary> 706 /// <summary>
706 /// A worker thread method that processes work items from the work items queue. 707 /// A worker thread method that processes work items from the work items queue.
707 /// </summary> 708 /// </summary>
708 private void ProcessQueuedItems() 709 private void ProcessQueuedItems()
709 { 710 {
710 // Keep the entry of the dictionary as thread's variable to avoid the synchronization locks 711 // Keep the entry of the dictionary as thread's variable to avoid the synchronization locks
711 // of the dictionary. 712 // of the dictionary.
712 CurrentThreadEntry = _workerThreads[Thread.CurrentThread]; 713 CurrentThreadEntry = _workerThreads[Thread.CurrentThread];
713 714
714 FireOnThreadInitialization(); 715 FireOnThreadInitialization();
715 716
716 try 717 try
717 { 718 {
718 bool bInUseWorkerThreadsWasIncremented = false; 719 bool bInUseWorkerThreadsWasIncremented = false;
719 720
720 // Process until shutdown. 721 // Process until shutdown.
721 while(!_shutdown) 722 while(!_shutdown)
722 { 723 {
723 // Update the last time this thread was seen alive. 724 // Update the last time this thread was seen alive.
724 // It's good for debugging. 725 // It's good for debugging.
725 CurrentThreadEntry.IAmAlive(); 726 CurrentThreadEntry.IAmAlive();
726 727
727 // The following block handles the when the MaxWorkerThreads has been 728 // The following block handles the when the MaxWorkerThreads has been
@@ -743,166 +744,166 @@ namespace Amib.Threading
743 } 744 }
744 } 745 }
745 746
746 // Wait for a work item, shutdown, or timeout 747 // Wait for a work item, shutdown, or timeout
747 WorkItem workItem = Dequeue(); 748 WorkItem workItem = Dequeue();
748 749
749 // Update the last time this thread was seen alive. 750 // Update the last time this thread was seen alive.
750 // It's good for debugging. 751 // It's good for debugging.
751 CurrentThreadEntry.IAmAlive(); 752 CurrentThreadEntry.IAmAlive();
752 753
753 // On timeout or shut down. 754 // On timeout or shut down.
754 if (null == workItem) 755 if (null == workItem)
755 { 756 {
756 // Double lock for quit. 757 // Double lock for quit.
757 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads) 758 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
758 { 759 {
759 lock(_workerThreads.SyncRoot) 760 lock(_workerThreads.SyncRoot)
760 { 761 {
761 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads) 762 if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads)
762 { 763 {
763 // Inform that the thread is quiting and then quit. 764 // Inform that the thread is quiting and then quit.
764 // This method must be called within this lock or else 765 // This method must be called within this lock or else
765 // more threads will quit and the thread pool will go 766 // more threads will quit and the thread pool will go
766 // below the lower limit. 767 // below the lower limit.
767 InformCompleted(); 768 InformCompleted();
768 break; 769 break;
769 } 770 }
770 } 771 }
771 } 772 }
772 } 773 }
773 774
774 // If we didn't quit then skip to the next iteration. 775 // If we didn't quit then skip to the next iteration.
775 if (null == workItem) 776 if (null == workItem)
776 { 777 {
777 continue; 778 continue;
778 } 779 }
779 780
780 try 781 try
781 { 782 {
782 // Initialize the value to false 783 // Initialize the value to false
783 bInUseWorkerThreadsWasIncremented = false; 784 bInUseWorkerThreadsWasIncremented = false;
784 785
785 // Set the Current Work Item of the thread. 786 // Set the Current Work Item of the thread.
786 // Store the Current Work Item before the workItem.StartingWorkItem() is called, 787 // Store the Current Work Item before the workItem.StartingWorkItem() is called,
787 // so WorkItem.Cancel can work when the work item is between InQueue and InProgress 788 // so WorkItem.Cancel can work when the work item is between InQueue and InProgress
788 // states. 789 // states.
789 // If the work item has been cancelled BEFORE the workItem.StartingWorkItem() 790 // If the work item has been cancelled BEFORE the workItem.StartingWorkItem()
790 // (work item is in InQueue state) then workItem.StartingWorkItem() will return false. 791 // (work item is in InQueue state) then workItem.StartingWorkItem() will return false.
791 // If the work item has been cancelled AFTER the workItem.StartingWorkItem() then 792 // If the work item has been cancelled AFTER the workItem.StartingWorkItem() then
792 // (work item is in InProgress state) then the thread will be aborted 793 // (work item is in InProgress state) then the thread will be aborted
793 CurrentThreadEntry.CurrentWorkItem = workItem; 794 CurrentThreadEntry.CurrentWorkItem = workItem;
794 795
795 // Change the state of the work item to 'in progress' if possible. 796 // Change the state of the work item to 'in progress' if possible.
796 // We do it here so if the work item has been canceled we won't 797 // We do it here so if the work item has been canceled we won't
797 // increment the _inUseWorkerThreads. 798 // increment the _inUseWorkerThreads.
798 // The cancel mechanism doesn't delete items from the queue, 799 // The cancel mechanism doesn't delete items from the queue,
799 // it marks the work item as canceled, and when the work item 800 // it marks the work item as canceled, and when the work item
800 // is dequeued, we just skip it. 801 // is dequeued, we just skip it.
801 // If the post execute of work item is set to always or to 802 // If the post execute of work item is set to always or to
802 // call when the work item is canceled then the StartingWorkItem() 803 // call when the work item is canceled then the StartingWorkItem()
803 // will return true, so the post execute can run. 804 // will return true, so the post execute can run.
804 if (!workItem.StartingWorkItem()) 805 if (!workItem.StartingWorkItem())
805 { 806 {
806 continue; 807 continue;
807 } 808 }
808 809
809 // Execute the callback. Make sure to accurately 810 // Execute the callback. Make sure to accurately
810 // record how many callbacks are currently executing. 811 // record how many callbacks are currently executing.
811 int inUseWorkerThreads = Interlocked.Increment(ref _inUseWorkerThreads); 812 int inUseWorkerThreads = Interlocked.Increment(ref _inUseWorkerThreads);
812 _windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads); 813 _windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
813 _localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads); 814 _localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
814 815
815 // Mark that the _inUseWorkerThreads incremented, so in the finally{} 816 // Mark that the _inUseWorkerThreads incremented, so in the finally{}
816 // statement we will decrement it correctly. 817 // statement we will decrement it correctly.
817 bInUseWorkerThreadsWasIncremented = true; 818 bInUseWorkerThreadsWasIncremented = true;
818 819
819 workItem.FireWorkItemStarted(); 820 workItem.FireWorkItemStarted();
820 821
821 ExecuteWorkItem(workItem); 822 ExecuteWorkItem(workItem);
822 } 823 }
823 catch(Exception ex) 824 catch(Exception ex)
824 { 825 {
825 ex.GetHashCode(); 826 ex.GetHashCode();
826 // Do nothing 827 // Do nothing
827 } 828 }
828 finally 829 finally
829 { 830 {
830 workItem.DisposeOfState(); 831 workItem.DisposeOfState();
831 832
832 // Set the CurrentWorkItem to null, since we 833 // Set the CurrentWorkItem to null, since we
833 // no longer run user's code. 834 // no longer run user's code.
834 CurrentThreadEntry.CurrentWorkItem = null; 835 CurrentThreadEntry.CurrentWorkItem = null;
835 836
836 // Decrement the _inUseWorkerThreads only if we had 837 // Decrement the _inUseWorkerThreads only if we had
837 // incremented it. Note the cancelled work items don't 838 // incremented it. Note the cancelled work items don't
838 // increment _inUseWorkerThreads. 839 // increment _inUseWorkerThreads.
839 if (bInUseWorkerThreadsWasIncremented) 840 if (bInUseWorkerThreadsWasIncremented)
840 { 841 {
841 int inUseWorkerThreads = Interlocked.Decrement(ref _inUseWorkerThreads); 842 int inUseWorkerThreads = Interlocked.Decrement(ref _inUseWorkerThreads);
842 _windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads); 843 _windowsPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
843 _localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads); 844 _localPCs.SampleThreads(_workerThreads.Count, inUseWorkerThreads);
844 } 845 }
845 846
846 // Notify that the work item has been completed. 847 // Notify that the work item has been completed.
847 // WorkItemsGroup may enqueue their next work item. 848 // WorkItemsGroup may enqueue their next work item.
848 workItem.FireWorkItemCompleted(); 849 workItem.FireWorkItemCompleted();
849 850
850 // Decrement the number of work items here so the idle 851 // Decrement the number of work items here so the idle
851 // ManualResetEvent won't fluctuate. 852 // ManualResetEvent won't fluctuate.
852 DecrementWorkItemsCount(); 853 DecrementWorkItemsCount();
853 } 854 }
854 } 855 }
855 } 856 }
856 catch(ThreadAbortException tae) 857 catch(ThreadAbortException tae)
857 { 858 {
858 tae.GetHashCode(); 859 tae.GetHashCode();
859 // Handle the abort exception gracfully. 860 // Handle the abort exception gracfully.
860#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) 861#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
861 Thread.ResetAbort(); 862 Thread.ResetAbort();
862#endif 863#endif
863 } 864 }
864 catch(Exception e) 865 catch(Exception e)
865 { 866 {
866 Debug.Assert(null != e); 867 Debug.Assert(null != e);
867 } 868 }
868 finally 869 finally
869 { 870 {
870 InformCompleted(); 871 InformCompleted();
871 FireOnThreadTermination(); 872 FireOnThreadTermination();
872 } 873 }
873 } 874 }
874 875
875 private void ExecuteWorkItem(WorkItem workItem) 876 private void ExecuteWorkItem(WorkItem workItem)
876 { 877 {
877 _windowsPCs.SampleWorkItemsWaitTime(workItem.WaitingTime); 878 _windowsPCs.SampleWorkItemsWaitTime(workItem.WaitingTime);
878 _localPCs.SampleWorkItemsWaitTime(workItem.WaitingTime); 879 _localPCs.SampleWorkItemsWaitTime(workItem.WaitingTime);
879 try 880 try
880 { 881 {
881 workItem.Execute(); 882 workItem.Execute();
882 } 883 }
883 finally 884 finally
884 { 885 {
885 _windowsPCs.SampleWorkItemsProcessTime(workItem.ProcessTime); 886 _windowsPCs.SampleWorkItemsProcessTime(workItem.ProcessTime);
886 _localPCs.SampleWorkItemsProcessTime(workItem.ProcessTime); 887 _localPCs.SampleWorkItemsProcessTime(workItem.ProcessTime);
887 } 888 }
888 } 889 }
889 890
890 891
891 #endregion 892 #endregion
892 893
893 #region Public Methods 894 #region Public Methods
894 895
895 private void ValidateWaitForIdle() 896 private void ValidateWaitForIdle()
896 { 897 {
897 if (null != CurrentThreadEntry && CurrentThreadEntry.AssociatedSmartThreadPool == this) 898 if (null != CurrentThreadEntry && CurrentThreadEntry.AssociatedSmartThreadPool == this)
898 { 899 {
899 throw new NotSupportedException( 900 throw new NotSupportedException(
900 "WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock"); 901 "WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
901 } 902 }
902 } 903 }
903 904
904 internal static void ValidateWorkItemsGroupWaitForIdle(IWorkItemsGroup workItemsGroup) 905 internal static void ValidateWorkItemsGroupWaitForIdle(IWorkItemsGroup workItemsGroup)
905 { 906 {
906 if (null == CurrentThreadEntry) 907 if (null == CurrentThreadEntry)
907 { 908 {
908 return; 909 return;
@@ -910,334 +911,334 @@ namespace Amib.Threading
910 911
911 WorkItem workItem = CurrentThreadEntry.CurrentWorkItem; 912 WorkItem workItem = CurrentThreadEntry.CurrentWorkItem;
912 ValidateWorkItemsGroupWaitForIdleImpl(workItemsGroup, workItem); 913 ValidateWorkItemsGroupWaitForIdleImpl(workItemsGroup, workItem);
913 if ((null != workItemsGroup) && 914 if ((null != workItemsGroup) &&
914 (null != workItem) && 915 (null != workItem) &&
915 CurrentThreadEntry.CurrentWorkItem.WasQueuedBy(workItemsGroup)) 916 CurrentThreadEntry.CurrentWorkItem.WasQueuedBy(workItemsGroup))
916 { 917 {
917 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock"); 918 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
918 } 919 }
919 } 920 }
920 921
921 [MethodImpl(MethodImplOptions.NoInlining)] 922 [MethodImpl(MethodImplOptions.NoInlining)]
922 private static void ValidateWorkItemsGroupWaitForIdleImpl(IWorkItemsGroup workItemsGroup, WorkItem workItem) 923 private static void ValidateWorkItemsGroupWaitForIdleImpl(IWorkItemsGroup workItemsGroup, WorkItem workItem)
923 { 924 {
924 if ((null != workItemsGroup) && 925 if ((null != workItemsGroup) &&
925 (null != workItem) && 926 (null != workItem) &&
926 workItem.WasQueuedBy(workItemsGroup)) 927 workItem.WasQueuedBy(workItemsGroup))
927 { 928 {
928 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock"); 929 throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
929 } 930 }
930 } 931 }
931 932
932 /// <summary> 933 /// <summary>
933 /// Force the SmartThreadPool to shutdown 934 /// Force the SmartThreadPool to shutdown
934 /// </summary> 935 /// </summary>
935 public void Shutdown() 936 public void Shutdown()
936 { 937 {
937 Shutdown(true, 0); 938 Shutdown(true, 0);
938 } 939 }
939 940
940 /// <summary> 941 /// <summary>
941 /// Force the SmartThreadPool to shutdown with timeout 942 /// Force the SmartThreadPool to shutdown with timeout
942 /// </summary> 943 /// </summary>
943 public void Shutdown(bool forceAbort, TimeSpan timeout) 944 public void Shutdown(bool forceAbort, TimeSpan timeout)
944 { 945 {
945 Shutdown(forceAbort, (int)timeout.TotalMilliseconds); 946 Shutdown(forceAbort, (int)timeout.TotalMilliseconds);
946 } 947 }
947 948
948 /// <summary> 949 /// <summary>
949 /// Empties the queue of work items and abort the threads in the pool. 950 /// Empties the queue of work items and abort the threads in the pool.
950 /// </summary> 951 /// </summary>
951 public void Shutdown(bool forceAbort, int millisecondsTimeout) 952 public void Shutdown(bool forceAbort, int millisecondsTimeout)
952 { 953 {
953 ValidateNotDisposed(); 954 ValidateNotDisposed();
954 955
955 ISTPInstancePerformanceCounters pcs = _windowsPCs; 956 ISTPInstancePerformanceCounters pcs = _windowsPCs;
956 957
957 if (NullSTPInstancePerformanceCounters.Instance != _windowsPCs) 958 if (NullSTPInstancePerformanceCounters.Instance != _windowsPCs)
958 { 959 {
959 // Set the _pcs to "null" to stop updating the performance 960 // Set the _pcs to "null" to stop updating the performance
960 // counters 961 // counters
961 _windowsPCs = NullSTPInstancePerformanceCounters.Instance; 962 _windowsPCs = NullSTPInstancePerformanceCounters.Instance;
962 963
963 pcs.Dispose(); 964 pcs.Dispose();
964 } 965 }
965 966
966 Thread [] threads; 967 Thread [] threads;
967 lock(_workerThreads.SyncRoot) 968 lock(_workerThreads.SyncRoot)
968 { 969 {
969 // Shutdown the work items queue 970 // Shutdown the work items queue
970 _workItemsQueue.Dispose(); 971 _workItemsQueue.Dispose();
971 972
972 // Signal the threads to exit 973 // Signal the threads to exit
973 _shutdown = true; 974 _shutdown = true;
974 _shuttingDownEvent.Set(); 975 _shuttingDownEvent.Set();
975 976
976 // Make a copy of the threads' references in the pool 977 // Make a copy of the threads' references in the pool
977 threads = new Thread [_workerThreads.Count]; 978 threads = new Thread [_workerThreads.Count];
978 _workerThreads.Keys.CopyTo(threads, 0); 979 _workerThreads.Keys.CopyTo(threads, 0);
979 } 980 }
980 981
981 int millisecondsLeft = millisecondsTimeout; 982 int millisecondsLeft = millisecondsTimeout;
982 Stopwatch stopwatch = Stopwatch.StartNew(); 983 Stopwatch stopwatch = Stopwatch.StartNew();
983 //DateTime start = DateTime.UtcNow; 984 //DateTime start = DateTime.UtcNow;
984 bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout); 985 bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
985 bool timeout = false; 986 bool timeout = false;
986 987
987 // Each iteration we update the time left for the timeout. 988 // Each iteration we update the time left for the timeout.
988 foreach(Thread thread in threads) 989 foreach(Thread thread in threads)
989 { 990 {
990 // Join don't work with negative numbers 991 // Join don't work with negative numbers
991 if (!waitInfinitely && (millisecondsLeft < 0)) 992 if (!waitInfinitely && (millisecondsLeft < 0))
992 { 993 {
993 timeout = true; 994 timeout = true;
994 break; 995 break;
995 } 996 }
996 997
997 // Wait for the thread to terminate 998 // Wait for the thread to terminate
998 bool success = thread.Join(millisecondsLeft); 999 bool success = thread.Join(millisecondsLeft);
999 if(!success) 1000 if(!success)
1000 { 1001 {
1001 timeout = true; 1002 timeout = true;
1002 break; 1003 break;
1003 } 1004 }
1004 1005
1005 if(!waitInfinitely) 1006 if(!waitInfinitely)
1006 { 1007 {
1007 // Update the time left to wait 1008 // Update the time left to wait
1008 //TimeSpan ts = DateTime.UtcNow - start; 1009 //TimeSpan ts = DateTime.UtcNow - start;
1009 millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds; 1010 millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
1010 } 1011 }
1011 } 1012 }
1012 1013
1013 if (timeout && forceAbort) 1014 if (timeout && forceAbort)
1014 { 1015 {
1015 // Abort the threads in the pool 1016 // Abort the threads in the pool
1016 foreach(Thread thread in threads) 1017 foreach(Thread thread in threads)
1017 { 1018 {
1018 1019
1019 if ((thread != null) 1020 if ((thread != null)
1020#if !(_WINDOWS_CE) 1021#if !(_WINDOWS_CE)
1021 && thread.IsAlive 1022 && thread.IsAlive
1022#endif 1023#endif
1023 ) 1024 )
1024 { 1025 {
1025 try 1026 try
1026 { 1027 {
1027 thread.Abort(); // Shutdown 1028 thread.Abort(); // Shutdown
1028 } 1029 }
1029 catch(SecurityException e) 1030 catch(SecurityException e)
1030 { 1031 {
1031 e.GetHashCode(); 1032 e.GetHashCode();
1032 } 1033 }
1033 catch(ThreadStateException ex) 1034 catch(ThreadStateException ex)
1034 { 1035 {
1035 ex.GetHashCode(); 1036 ex.GetHashCode();
1036 // In case the thread has been terminated 1037 // In case the thread has been terminated
1037 // after the check if it is alive. 1038 // after the check if it is alive.
1038 } 1039 }
1039 } 1040 }
1040 } 1041 }
1041 } 1042 }
1042 } 1043 }
1043 1044
1044 /// <summary> 1045 /// <summary>
1045 /// Wait for all work items to complete 1046 /// Wait for all work items to complete
1046 /// </summary> 1047 /// </summary>
1047 /// <param name="waitableResults">Array of work item result objects</param> 1048 /// <param name="waitableResults">Array of work item result objects</param>
1048 /// <returns> 1049 /// <returns>
1049 /// true when every work item in workItemResults has completed; otherwise false. 1050 /// true when every work item in workItemResults has completed; otherwise false.
1050 /// </returns> 1051 /// </returns>
1051 public static bool WaitAll( 1052 public static bool WaitAll(
1052 IWaitableResult [] waitableResults) 1053 IWaitableResult [] waitableResults)
1053 { 1054 {
1054 return WaitAll(waitableResults, Timeout.Infinite, true); 1055 return WaitAll(waitableResults, Timeout.Infinite, true);
1055 } 1056 }
1056 1057
1057 /// <summary> 1058 /// <summary>
1058 /// Wait for all work items to complete 1059 /// Wait for all work items to complete
1059 /// </summary> 1060 /// </summary>
1060 /// <param name="waitableResults">Array of work item result objects</param> 1061 /// <param name="waitableResults">Array of work item result objects</param>
1061 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param> 1062 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1062 /// <param name="exitContext"> 1063 /// <param name="exitContext">
1063 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1064 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1064 /// </param> 1065 /// </param>
1065 /// <returns> 1066 /// <returns>
1066 /// true when every work item in workItemResults has completed; otherwise false. 1067 /// true when every work item in workItemResults has completed; otherwise false.
1067 /// </returns> 1068 /// </returns>
1068 public static bool WaitAll( 1069 public static bool WaitAll(
1069 IWaitableResult [] waitableResults, 1070 IWaitableResult [] waitableResults,
1070 TimeSpan timeout, 1071 TimeSpan timeout,
1071 bool exitContext) 1072 bool exitContext)
1072 { 1073 {
1073 return WaitAll(waitableResults, (int)timeout.TotalMilliseconds, exitContext); 1074 return WaitAll(waitableResults, (int)timeout.TotalMilliseconds, exitContext);
1074 } 1075 }
1075 1076
1076 /// <summary> 1077 /// <summary>
1077 /// Wait for all work items to complete 1078 /// Wait for all work items to complete
1078 /// </summary> 1079 /// </summary>
1079 /// <param name="waitableResults">Array of work item result objects</param> 1080 /// <param name="waitableResults">Array of work item result objects</param>
1080 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param> 1081 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1081 /// <param name="exitContext"> 1082 /// <param name="exitContext">
1082 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1083 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1083 /// </param> 1084 /// </param>
1084 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 1085 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1085 /// <returns> 1086 /// <returns>
1086 /// true when every work item in workItemResults has completed; otherwise false. 1087 /// true when every work item in workItemResults has completed; otherwise false.
1087 /// </returns> 1088 /// </returns>
1088 public static bool WaitAll( 1089 public static bool WaitAll(
1089 IWaitableResult[] waitableResults, 1090 IWaitableResult[] waitableResults,
1090 TimeSpan timeout, 1091 TimeSpan timeout,
1091 bool exitContext, 1092 bool exitContext,
1092 WaitHandle cancelWaitHandle) 1093 WaitHandle cancelWaitHandle)
1093 { 1094 {
1094 return WaitAll(waitableResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle); 1095 return WaitAll(waitableResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
1095 } 1096 }
1096 1097
1097 /// <summary> 1098 /// <summary>
1098 /// Wait for all work items to complete 1099 /// Wait for all work items to complete
1099 /// </summary> 1100 /// </summary>
1100 /// <param name="waitableResults">Array of work item result objects</param> 1101 /// <param name="waitableResults">Array of work item result objects</param>
1101 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 1102 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1102 /// <param name="exitContext"> 1103 /// <param name="exitContext">
1103 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1104 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1104 /// </param> 1105 /// </param>
1105 /// <returns> 1106 /// <returns>
1106 /// true when every work item in workItemResults has completed; otherwise false. 1107 /// true when every work item in workItemResults has completed; otherwise false.
1107 /// </returns> 1108 /// </returns>
1108 public static bool WaitAll( 1109 public static bool WaitAll(
1109 IWaitableResult [] waitableResults, 1110 IWaitableResult [] waitableResults,
1110 int millisecondsTimeout, 1111 int millisecondsTimeout,
1111 bool exitContext) 1112 bool exitContext)
1112 { 1113 {
1113 return WorkItem.WaitAll(waitableResults, millisecondsTimeout, exitContext, null); 1114 return WorkItem.WaitAll(waitableResults, millisecondsTimeout, exitContext, null);
1114 } 1115 }
1115 1116
1116 /// <summary> 1117 /// <summary>
1117 /// Wait for all work items to complete 1118 /// Wait for all work items to complete
1118 /// </summary> 1119 /// </summary>
1119 /// <param name="waitableResults">Array of work item result objects</param> 1120 /// <param name="waitableResults">Array of work item result objects</param>
1120 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 1121 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1121 /// <param name="exitContext"> 1122 /// <param name="exitContext">
1122 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1123 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1123 /// </param> 1124 /// </param>
1124 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 1125 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1125 /// <returns> 1126 /// <returns>
1126 /// true when every work item in workItemResults has completed; otherwise false. 1127 /// true when every work item in workItemResults has completed; otherwise false.
1127 /// </returns> 1128 /// </returns>
1128 public static bool WaitAll( 1129 public static bool WaitAll(
1129 IWaitableResult[] waitableResults, 1130 IWaitableResult[] waitableResults,
1130 int millisecondsTimeout, 1131 int millisecondsTimeout,
1131 bool exitContext, 1132 bool exitContext,
1132 WaitHandle cancelWaitHandle) 1133 WaitHandle cancelWaitHandle)
1133 { 1134 {
1134 return WorkItem.WaitAll(waitableResults, millisecondsTimeout, exitContext, cancelWaitHandle); 1135 return WorkItem.WaitAll(waitableResults, millisecondsTimeout, exitContext, cancelWaitHandle);
1135 } 1136 }
1136 1137
1137 1138
1138 /// <summary> 1139 /// <summary>
1139 /// Waits for any of the work items in the specified array to complete, cancel, or timeout 1140 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1140 /// </summary> 1141 /// </summary>
1141 /// <param name="waitableResults">Array of work item result objects</param> 1142 /// <param name="waitableResults">Array of work item result objects</param>
1142 /// <returns> 1143 /// <returns>
1143 /// The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled. 1144 /// The array index of the work item result that satisfied the wait, or WaitTimeout if any of the work items has been canceled.
1144 /// </returns> 1145 /// </returns>
1145 public static int WaitAny( 1146 public static int WaitAny(
1146 IWaitableResult [] waitableResults) 1147 IWaitableResult [] waitableResults)
1147 { 1148 {
1148 return WaitAny(waitableResults, Timeout.Infinite, true); 1149 return WaitAny(waitableResults, Timeout.Infinite, true);
1149 } 1150 }
1150 1151
1151 /// <summary> 1152 /// <summary>
1152 /// Waits for any of the work items in the specified array to complete, cancel, or timeout 1153 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1153 /// </summary> 1154 /// </summary>
1154 /// <param name="waitableResults">Array of work item result objects</param> 1155 /// <param name="waitableResults">Array of work item result objects</param>
1155 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param> 1156 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1156 /// <param name="exitContext"> 1157 /// <param name="exitContext">
1157 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1158 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1158 /// </param> 1159 /// </param>
1159 /// <returns> 1160 /// <returns>
1160 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. 1161 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1161 /// </returns> 1162 /// </returns>
1162 public static int WaitAny( 1163 public static int WaitAny(
1163 IWaitableResult[] waitableResults, 1164 IWaitableResult[] waitableResults,
1164 TimeSpan timeout, 1165 TimeSpan timeout,
1165 bool exitContext) 1166 bool exitContext)
1166 { 1167 {
1167 return WaitAny(waitableResults, (int)timeout.TotalMilliseconds, exitContext); 1168 return WaitAny(waitableResults, (int)timeout.TotalMilliseconds, exitContext);
1168 } 1169 }
1169 1170
1170 /// <summary> 1171 /// <summary>
1171 /// Waits for any of the work items in the specified array to complete, cancel, or timeout 1172 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1172 /// </summary> 1173 /// </summary>
1173 /// <param name="waitableResults">Array of work item result objects</param> 1174 /// <param name="waitableResults">Array of work item result objects</param>
1174 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param> 1175 /// <param name="timeout">The number of milliseconds to wait, or a TimeSpan that represents -1 milliseconds to wait indefinitely. </param>
1175 /// <param name="exitContext"> 1176 /// <param name="exitContext">
1176 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1177 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1177 /// </param> 1178 /// </param>
1178 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 1179 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1179 /// <returns> 1180 /// <returns>
1180 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. 1181 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1181 /// </returns> 1182 /// </returns>
1182 public static int WaitAny( 1183 public static int WaitAny(
1183 IWaitableResult [] waitableResults, 1184 IWaitableResult [] waitableResults,
1184 TimeSpan timeout, 1185 TimeSpan timeout,
1185 bool exitContext, 1186 bool exitContext,
1186 WaitHandle cancelWaitHandle) 1187 WaitHandle cancelWaitHandle)
1187 { 1188 {
1188 return WaitAny(waitableResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle); 1189 return WaitAny(waitableResults, (int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
1189 } 1190 }
1190 1191
1191 /// <summary> 1192 /// <summary>
1192 /// Waits for any of the work items in the specified array to complete, cancel, or timeout 1193 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1193 /// </summary> 1194 /// </summary>
1194 /// <param name="waitableResults">Array of work item result objects</param> 1195 /// <param name="waitableResults">Array of work item result objects</param>
1195 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 1196 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1196 /// <param name="exitContext"> 1197 /// <param name="exitContext">
1197 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1198 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1198 /// </param> 1199 /// </param>
1199 /// <returns> 1200 /// <returns>
1200 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. 1201 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1201 /// </returns> 1202 /// </returns>
1202 public static int WaitAny( 1203 public static int WaitAny(
1203 IWaitableResult [] waitableResults, 1204 IWaitableResult [] waitableResults,
1204 int millisecondsTimeout, 1205 int millisecondsTimeout,
1205 bool exitContext) 1206 bool exitContext)
1206 { 1207 {
1207 return WorkItem.WaitAny(waitableResults, millisecondsTimeout, exitContext, null); 1208 return WorkItem.WaitAny(waitableResults, millisecondsTimeout, exitContext, null);
1208 } 1209 }
1209 1210
1210 /// <summary> 1211 /// <summary>
1211 /// Waits for any of the work items in the specified array to complete, cancel, or timeout 1212 /// Waits for any of the work items in the specified array to complete, cancel, or timeout
1212 /// </summary> 1213 /// </summary>
1213 /// <param name="waitableResults">Array of work item result objects</param> 1214 /// <param name="waitableResults">Array of work item result objects</param>
1214 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 1215 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
1215 /// <param name="exitContext"> 1216 /// <param name="exitContext">
1216 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 1217 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
1217 /// </param> 1218 /// </param>
1218 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 1219 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
1219 /// <returns> 1220 /// <returns>
1220 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled. 1221 /// The array index of the work item result that satisfied the wait, or WaitTimeout if no work item result satisfied the wait and a time interval equivalent to millisecondsTimeout has passed or the work item has been canceled.
1221 /// </returns> 1222 /// </returns>
1222 public static int WaitAny( 1223 public static int WaitAny(
1223 IWaitableResult [] waitableResults, 1224 IWaitableResult [] waitableResults,
1224 int millisecondsTimeout, 1225 int millisecondsTimeout,
1225 bool exitContext, 1226 bool exitContext,
1226 WaitHandle cancelWaitHandle) 1227 WaitHandle cancelWaitHandle)
1227 { 1228 {
1228 return WorkItem.WaitAny(waitableResults, millisecondsTimeout, exitContext, cancelWaitHandle); 1229 return WorkItem.WaitAny(waitableResults, millisecondsTimeout, exitContext, cancelWaitHandle);
1229 } 1230 }
1230 1231
1231 /// <summary> 1232 /// <summary>
1232 /// Creates a new WorkItemsGroup. 1233 /// Creates a new WorkItemsGroup.
1233 /// </summary> 1234 /// </summary>
1234 /// <param name="concurrency">The number of work items that can be run concurrently</param> 1235 /// <param name="concurrency">The number of work items that can be run concurrently</param>
1235 /// <returns>A reference to the WorkItemsGroup</returns> 1236 /// <returns>A reference to the WorkItemsGroup</returns>
1236 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency) 1237 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency)
1237 { 1238 {
1238 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, _stpStartInfo); 1239 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, _stpStartInfo);
1239 return workItemsGroup; 1240 return workItemsGroup;
1240 } 1241 }
1241 1242
1242 /// <summary> 1243 /// <summary>
1243 /// Creates a new WorkItemsGroup. 1244 /// Creates a new WorkItemsGroup.
@@ -1245,11 +1246,11 @@ namespace Amib.Threading
1245 /// <param name="concurrency">The number of work items that can be run concurrently</param> 1246 /// <param name="concurrency">The number of work items that can be run concurrently</param>
1246 /// <param name="wigStartInfo">A WorkItemsGroup configuration that overrides the default behavior</param> 1247 /// <param name="wigStartInfo">A WorkItemsGroup configuration that overrides the default behavior</param>
1247 /// <returns>A reference to the WorkItemsGroup</returns> 1248 /// <returns>A reference to the WorkItemsGroup</returns>
1248 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency, WIGStartInfo wigStartInfo) 1249 public IWorkItemsGroup CreateWorkItemsGroup(int concurrency, WIGStartInfo wigStartInfo)
1249 { 1250 {
1250 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, wigStartInfo); 1251 IWorkItemsGroup workItemsGroup = new WorkItemsGroup(this, concurrency, wigStartInfo);
1251 return workItemsGroup; 1252 return workItemsGroup;
1252 } 1253 }
1253 1254
1254 #region Fire Thread's Events 1255 #region Fire Thread's Events
1255 1256
@@ -1330,22 +1331,22 @@ namespace Amib.Threading
1330 } 1331 }
1331 } 1332 }
1332 1333
1333
1334 1334
1335 #endregion
1336 1335
1337 #region Properties 1336 #endregion
1338 1337
1339 /// <summary> 1338 #region Properties
1340 /// Get/Set the lower limit of threads in the pool. 1339
1341 /// </summary> 1340 /// <summary>
1342 public int MinThreads 1341 /// Get/Set the lower limit of threads in the pool.
1343 { 1342 /// </summary>
1344 get 1343 public int MinThreads
1345 { 1344 {
1346 ValidateNotDisposed(); 1345 get
1347 return _stpStartInfo.MinWorkerThreads; 1346 {
1348 } 1347 ValidateNotDisposed();
1348 return _stpStartInfo.MinWorkerThreads;
1349 }
1349 set 1350 set
1350 { 1351 {
1351 Debug.Assert(value >= 0); 1352 Debug.Assert(value >= 0);
@@ -1357,21 +1358,21 @@ namespace Amib.Threading
1357 _stpStartInfo.MinWorkerThreads = value; 1358 _stpStartInfo.MinWorkerThreads = value;
1358 StartOptimalNumberOfThreads(); 1359 StartOptimalNumberOfThreads();
1359 } 1360 }
1360 } 1361 }
1361 1362
1362 /// <summary> 1363 /// <summary>
1363 /// Get/Set the upper limit of threads in the pool. 1364 /// Get/Set the upper limit of threads in the pool.
1364 /// </summary> 1365 /// </summary>
1365 public int MaxThreads 1366 public int MaxThreads
1366 { 1367 {
1367 get 1368 get
1368 { 1369 {
1369 ValidateNotDisposed(); 1370 ValidateNotDisposed();
1370 return _stpStartInfo.MaxWorkerThreads; 1371 return _stpStartInfo.MaxWorkerThreads;
1371 } 1372 }
1372 1373
1373 set 1374 set
1374 { 1375 {
1375 Debug.Assert(value > 0); 1376 Debug.Assert(value > 0);
1376 Debug.Assert(value >= _stpStartInfo.MinWorkerThreads); 1377 Debug.Assert(value >= _stpStartInfo.MinWorkerThreads);
1377 if (_stpStartInfo.MinWorkerThreads > value) 1378 if (_stpStartInfo.MinWorkerThreads > value)
@@ -1380,32 +1381,32 @@ namespace Amib.Threading
1380 } 1381 }
1381 _stpStartInfo.MaxWorkerThreads = value; 1382 _stpStartInfo.MaxWorkerThreads = value;
1382 StartOptimalNumberOfThreads(); 1383 StartOptimalNumberOfThreads();
1383 } 1384 }
1384 } 1385 }
1385 /// <summary> 1386 /// <summary>
1386 /// Get the number of threads in the thread pool. 1387 /// Get the number of threads in the thread pool.
1387 /// Should be between the lower and the upper limits. 1388 /// Should be between the lower and the upper limits.
1388 /// </summary> 1389 /// </summary>
1389 public int ActiveThreads 1390 public int ActiveThreads
1390 { 1391 {
1391 get 1392 get
1392 { 1393 {
1393 ValidateNotDisposed(); 1394 ValidateNotDisposed();
1394 return _workerThreads.Count; 1395 return _workerThreads.Count;
1395 } 1396 }
1396 } 1397 }
1397 1398
1398 /// <summary> 1399 /// <summary>
1399 /// Get the number of busy (not idle) threads in the thread pool. 1400 /// Get the number of busy (not idle) threads in the thread pool.
1400 /// </summary> 1401 /// </summary>
1401 public int InUseThreads 1402 public int InUseThreads
1402 { 1403 {
1403 get 1404 get
1404 { 1405 {
1405 ValidateNotDisposed(); 1406 ValidateNotDisposed();
1406 return _inUseWorkerThreads; 1407 return _inUseWorkerThreads;
1407 } 1408 }
1408 } 1409 }
1409 1410
1410 /// <summary> 1411 /// <summary>
1411 /// Returns true if the current running work item has been cancelled. 1412 /// Returns true if the current running work item has been cancelled.
@@ -1419,8 +1420,8 @@ namespace Amib.Threading
1419 { 1420 {
1420 return CurrentThreadEntry.CurrentWorkItem.IsCanceled; 1421 return CurrentThreadEntry.CurrentWorkItem.IsCanceled;
1421 } 1422 }
1422 } 1423 }
1423 1424
1424 /// <summary> 1425 /// <summary>
1425 /// Checks if the work item has been cancelled, and if yes then abort the thread. 1426 /// Checks if the work item has been cancelled, and if yes then abort the thread.
1426 /// Can be used with Cancel and timeout 1427 /// Can be used with Cancel and timeout
@@ -1438,16 +1439,16 @@ namespace Amib.Threading
1438 /// </summary> 1439 /// </summary>
1439 public STPStartInfo STPStartInfo 1440 public STPStartInfo STPStartInfo
1440 { 1441 {
1441 get 1442 get
1442 { 1443 {
1443 return _stpStartInfo.AsReadOnly(); 1444 return _stpStartInfo.AsReadOnly();
1444 } 1445 }
1445 } 1446 }
1446 1447
1447 public bool IsShuttingdown 1448 public bool IsShuttingdown
1448 { 1449 {
1449 get { return _shutdown; } 1450 get { return _shutdown; }
1450 } 1451 }
1451 1452
1452 /// <summary> 1453 /// <summary>
1453 /// Return the local calculated performance counters 1454 /// Return the local calculated performance counters
@@ -1477,13 +1478,16 @@ namespace Amib.Threading
1477 _shuttingDownEvent = null; 1478 _shuttingDownEvent = null;
1478 } 1479 }
1479 _workerThreads.Clear(); 1480 _workerThreads.Clear();
1480 1481
1481 if (null != _isIdleWaitHandle) 1482 if (null != _isIdleWaitHandle)
1482 { 1483 {
1483 _isIdleWaitHandle.Close(); 1484 _isIdleWaitHandle.Close();
1484 _isIdleWaitHandle = null; 1485 _isIdleWaitHandle = null;
1485 } 1486 }
1486 1487
1488 if (_stpStartInfo.EnableLocalPerformanceCounters)
1489 _localPCs.Dispose();
1490
1487 _isDisposed = true; 1491 _isDisposed = true;
1488 } 1492 }
1489 } 1493 }
@@ -1503,22 +1507,22 @@ namespace Amib.Threading
1503 /// Get/Set the maximum number of work items that execute cocurrency on the thread pool 1507 /// Get/Set the maximum number of work items that execute cocurrency on the thread pool
1504 /// </summary> 1508 /// </summary>
1505 public override int Concurrency 1509 public override int Concurrency
1506 { 1510 {
1507 get { return MaxThreads; } 1511 get { return MaxThreads; }
1508 set { MaxThreads = value; } 1512 set { MaxThreads = value; }
1509 } 1513 }
1510 1514
1511 /// <summary> 1515 /// <summary>
1512 /// Get the number of work items in the queue. 1516 /// Get the number of work items in the queue.
1513 /// </summary> 1517 /// </summary>
1514 public override int WaitingCallbacks 1518 public override int WaitingCallbacks
1515 { 1519 {
1516 get 1520 get
1517 { 1521 {
1518 ValidateNotDisposed(); 1522 ValidateNotDisposed();
1519 return _workItemsQueue.Count; 1523 return _workItemsQueue.Count;
1520 } 1524 }
1521 } 1525 }
1522 1526
1523 /// <summary> 1527 /// <summary>
1524 /// Get an array with all the state objects of the currently running items. 1528 /// Get an array with all the state objects of the currently running items.
@@ -1538,7 +1542,7 @@ namespace Amib.Threading
1538 get { return _stpStartInfo.AsReadOnly(); } 1542 get { return _stpStartInfo.AsReadOnly(); }
1539 } 1543 }
1540 1544
1541 /// <summary> 1545 /// <summary>
1542 /// Start the thread pool if it was started suspended. 1546 /// Start the thread pool if it was started suspended.
1543 /// If it is already running, this method is ignored. 1547 /// If it is already running, this method is ignored.
1544 /// </summary> 1548 /// </summary>
@@ -1589,7 +1593,7 @@ namespace Amib.Threading
1589 } 1593 }
1590 } 1594 }
1591 1595
1592 /// <summary> 1596 /// <summary>
1593 /// Wait for the thread pool to be idle 1597 /// Wait for the thread pool to be idle
1594 /// </summary> 1598 /// </summary>
1595 public override bool WaitForIdle(int millisecondsTimeout) 1599 public override bool WaitForIdle(int millisecondsTimeout)
@@ -1618,9 +1622,9 @@ namespace Amib.Threading
1618 } 1622 }
1619 } 1623 }
1620 1624
1621 internal override void PreQueueWorkItem() 1625 internal override void PreQueueWorkItem()
1622 { 1626 {
1623 ValidateNotDisposed(); 1627 ValidateNotDisposed();
1624 } 1628 }
1625 1629
1626 #endregion 1630 #endregion
@@ -1672,7 +1676,7 @@ namespace Amib.Threading
1672 ManualResetEvent anActionCompleted = new ManualResetEvent(false); 1676 ManualResetEvent anActionCompleted = new ManualResetEvent(false);
1673 1677
1674 ChoiceIndex choiceIndex = new ChoiceIndex(); 1678 ChoiceIndex choiceIndex = new ChoiceIndex();
1675 1679
1676 int i = 0; 1680 int i = 0;
1677 foreach (Action action in actions) 1681 foreach (Action action in actions)
1678 { 1682 {
@@ -1681,8 +1685,9 @@ namespace Amib.Threading
1681 workItemsGroup.QueueWorkItem(() => { act(); Interlocked.CompareExchange(ref choiceIndex._index, value, -1); anActionCompleted.Set(); }); 1685 workItemsGroup.QueueWorkItem(() => { act(); Interlocked.CompareExchange(ref choiceIndex._index, value, -1); anActionCompleted.Set(); });
1682 ++i; 1686 ++i;
1683 } 1687 }
1684 workItemsGroup.Start(); 1688 workItemsGroup.Start();
1685 anActionCompleted.WaitOne(); 1689 anActionCompleted.WaitOne();
1690 anActionCompleted.Dispose();
1686 1691
1687 return choiceIndex._index; 1692 return choiceIndex._index;
1688 } 1693 }
@@ -1693,7 +1698,7 @@ namespace Amib.Threading
1693 /// </summary> 1698 /// </summary>
1694 /// <param name="actions">Actions to execute</param> 1699 /// <param name="actions">Actions to execute</param>
1695 public int Choice(params Action[] actions) 1700 public int Choice(params Action[] actions)
1696 { 1701 {
1697 return Choice((IEnumerable<Action>)actions); 1702 return Choice((IEnumerable<Action>)actions);
1698 } 1703 }
1699 1704
@@ -1727,6 +1732,6 @@ namespace Amib.Threading
1727 Pipe(pipeState, (IEnumerable<Action<T>>)actions); 1732 Pipe(pipeState, (IEnumerable<Action<T>>)actions);
1728 } 1733 }
1729 #endregion 1734 #endregion
1730 } 1735 }
1731 #endregion 1736 #endregion
1732} 1737}
diff --git a/ThirdParty/SmartThreadPool/WIGStartInfo.cs b/ThirdParty/SmartThreadPool/WIGStartInfo.cs
index 8af195b..756ac1f 100644
--- a/ThirdParty/SmartThreadPool/WIGStartInfo.cs
+++ b/ThirdParty/SmartThreadPool/WIGStartInfo.cs
@@ -2,11 +2,11 @@ using System;
2 2
3namespace Amib.Threading 3namespace Amib.Threading
4{ 4{
5 /// <summary> 5 /// <summary>
6 /// Summary description for WIGStartInfo. 6 /// Summary description for WIGStartInfo.
7 /// </summary> 7 /// </summary>
8 public class WIGStartInfo 8 public class WIGStartInfo
9 { 9 {
10 private bool _useCallerCallContext; 10 private bool _useCallerCallContext;
11 private bool _useCallerHttpContext; 11 private bool _useCallerHttpContext;
12 private bool _disposeOfStateObjects; 12 private bool _disposeOfStateObjects;
@@ -18,10 +18,10 @@ namespace Amib.Threading
18 18
19 protected bool _readOnly; 19 protected bool _readOnly;
20 20
21 public WIGStartInfo() 21 public WIGStartInfo()
22 { 22 {
23 _fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs; 23 _fillStateWithArgs = SmartThreadPool.DefaultFillStateWithArgs;
24 _workItemPriority = SmartThreadPool.DefaultWorkItemPriority; 24 _workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
25 _startSuspended = SmartThreadPool.DefaultStartSuspended; 25 _startSuspended = SmartThreadPool.DefaultStartSuspended;
26 _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback; 26 _postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
27 _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute; 27 _callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
@@ -30,7 +30,7 @@ namespace Amib.Threading
30 _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext; 30 _useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
31 } 31 }
32 32
33 public WIGStartInfo(WIGStartInfo wigStartInfo) 33 public WIGStartInfo(WIGStartInfo wigStartInfo)
34 { 34 {
35 _useCallerCallContext = wigStartInfo.UseCallerCallContext; 35 _useCallerCallContext = wigStartInfo.UseCallerCallContext;
36 _useCallerHttpContext = wigStartInfo.UseCallerHttpContext; 36 _useCallerHttpContext = wigStartInfo.UseCallerHttpContext;
@@ -50,122 +50,122 @@ namespace Amib.Threading
50 } 50 }
51 } 51 }
52 52
53 /// <summary> 53 /// <summary>
54 /// Get/Set if to use the caller's security context 54 /// Get/Set if to use the caller's security context
55 /// </summary> 55 /// </summary>
56 public virtual bool UseCallerCallContext 56 public virtual bool UseCallerCallContext
57 { 57 {
58 get { return _useCallerCallContext; } 58 get { return _useCallerCallContext; }
59 set 59 set
60 { 60 {
61 ThrowIfReadOnly(); 61 ThrowIfReadOnly();
62 _useCallerCallContext = value; 62 _useCallerCallContext = value;
63 } 63 }
64 } 64 }
65 65
66 66
67 /// <summary> 67 /// <summary>
68 /// Get/Set if to use the caller's HTTP context 68 /// Get/Set if to use the caller's HTTP context
69 /// </summary> 69 /// </summary>
70 public virtual bool UseCallerHttpContext 70 public virtual bool UseCallerHttpContext
71 { 71 {
72 get { return _useCallerHttpContext; } 72 get { return _useCallerHttpContext; }
73 set 73 set
74 { 74 {
75 ThrowIfReadOnly(); 75 ThrowIfReadOnly();
76 _useCallerHttpContext = value; 76 _useCallerHttpContext = value;
77 } 77 }
78 } 78 }
79 79
80 80
81 /// <summary> 81 /// <summary>
82 /// Get/Set if to dispose of the state object of a work item 82 /// Get/Set if to dispose of the state object of a work item
83 /// </summary> 83 /// </summary>
84 public virtual bool DisposeOfStateObjects 84 public virtual bool DisposeOfStateObjects
85 { 85 {
86 get { return _disposeOfStateObjects; } 86 get { return _disposeOfStateObjects; }
87 set 87 set
88 { 88 {
89 ThrowIfReadOnly(); 89 ThrowIfReadOnly();
90 _disposeOfStateObjects = value; 90 _disposeOfStateObjects = value;
91 } 91 }
92 } 92 }
93 93
94 94
95 /// <summary> 95 /// <summary>
96 /// Get/Set the run the post execute options 96 /// Get/Set the run the post execute options
97 /// </summary> 97 /// </summary>
98 public virtual CallToPostExecute CallToPostExecute 98 public virtual CallToPostExecute CallToPostExecute
99 { 99 {
100 get { return _callToPostExecute; } 100 get { return _callToPostExecute; }
101 set 101 set
102 { 102 {
103 ThrowIfReadOnly(); 103 ThrowIfReadOnly();
104 _callToPostExecute = value; 104 _callToPostExecute = value;
105 } 105 }
106 } 106 }
107 107
108 108
109 /// <summary> 109 /// <summary>
110 /// Get/Set the default post execute callback 110 /// Get/Set the default post execute callback
111 /// </summary> 111 /// </summary>
112 public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback 112 public virtual PostExecuteWorkItemCallback PostExecuteWorkItemCallback
113 { 113 {
114 get { return _postExecuteWorkItemCallback; } 114 get { return _postExecuteWorkItemCallback; }
115 set 115 set
116 { 116 {
117 ThrowIfReadOnly(); 117 ThrowIfReadOnly();
118 _postExecuteWorkItemCallback = value; 118 _postExecuteWorkItemCallback = value;
119 } 119 }
120 } 120 }
121 121
122 122
123 /// <summary> 123 /// <summary>
124 /// Get/Set if the work items execution should be suspended until the Start() 124 /// Get/Set if the work items execution should be suspended until the Start()
125 /// method is called. 125 /// method is called.
126 /// </summary> 126 /// </summary>
127 public virtual bool StartSuspended 127 public virtual bool StartSuspended
128 { 128 {
129 get { return _startSuspended; } 129 get { return _startSuspended; }
130 set 130 set
131 { 131 {
132 ThrowIfReadOnly(); 132 ThrowIfReadOnly();
133 _startSuspended = value; 133 _startSuspended = value;
134 } 134 }
135 } 135 }
136 136
137 137
138 /// <summary> 138 /// <summary>
139 /// Get/Set the default priority that a work item gets when it is enqueued 139 /// Get/Set the default priority that a work item gets when it is enqueued
140 /// </summary> 140 /// </summary>
141 public virtual WorkItemPriority WorkItemPriority 141 public virtual WorkItemPriority WorkItemPriority
142 { 142 {
143 get { return _workItemPriority; } 143 get { return _workItemPriority; }
144 set { _workItemPriority = value; } 144 set { _workItemPriority = value; }
145 } 145 }
146 146
147 /// <summary> 147 /// <summary>
148 /// Get/Set the if QueueWorkItem of Action&lt;...&gt;/Func&lt;...&gt; fill the 148 /// Get/Set the if QueueWorkItem of Action&lt;...&gt;/Func&lt;...&gt; fill the
149 /// arguments as an object array into the state of the work item. 149 /// arguments as an object array into the state of the work item.
150 /// The arguments can be access later by IWorkItemResult.State. 150 /// The arguments can be access later by IWorkItemResult.State.
151 /// </summary> 151 /// </summary>
152 public virtual bool FillStateWithArgs 152 public virtual bool FillStateWithArgs
153 { 153 {
154 get { return _fillStateWithArgs; } 154 get { return _fillStateWithArgs; }
155 set 155 set
156 { 156 {
157 ThrowIfReadOnly(); 157 ThrowIfReadOnly();
158 _fillStateWithArgs = value; 158 _fillStateWithArgs = value;
159 } 159 }
160 } 160 }
161 161
162 /// <summary> 162 /// <summary>
163 /// Get a readonly version of this WIGStartInfo 163 /// Get a readonly version of this WIGStartInfo
164 /// </summary> 164 /// </summary>
165 /// <returns>Returns a readonly reference to this WIGStartInfoRO</returns> 165 /// <returns>Returns a readonly reference to this WIGStartInfoRO</returns>
166 public WIGStartInfo AsReadOnly() 166 public WIGStartInfo AsReadOnly()
167 { 167 {
168 return new WIGStartInfo(this) { _readOnly = true }; 168 return new WIGStartInfo(this) { _readOnly = true };
169 } 169 }
170 } 170 }
171} 171}
diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs
index 185f10c..edb8ac0 100644
--- a/ThirdParty/SmartThreadPool/WorkItem.cs
+++ b/ThirdParty/SmartThreadPool/WorkItem.cs
@@ -88,7 +88,7 @@ namespace Amib.Threading.Internal
88 private ManualResetEvent _workItemCompleted; 88 private ManualResetEvent _workItemCompleted;
89 89
90 /// <summary> 90 /// <summary>
91 /// A reference count to the _workItemCompleted. 91 /// A reference count to the _workItemCompleted.
92 /// When it reaches to zero _workItemCompleted is Closed 92 /// When it reaches to zero _workItemCompleted is Closed
93 /// </summary> 93 /// </summary>
94 private int _workItemCompletedRefCount; 94 private int _workItemCompletedRefCount;
@@ -114,13 +114,13 @@ namespace Amib.Threading.Internal
114 private event WorkItemStateCallback _workItemCompletedEvent; 114 private event WorkItemStateCallback _workItemCompletedEvent;
115 115
116 /// <summary> 116 /// <summary>
117 /// A reference to an object that indicates whatever the 117 /// A reference to an object that indicates whatever the
118 /// WorkItemsGroup has been canceled 118 /// WorkItemsGroup has been canceled
119 /// </summary> 119 /// </summary>
120 private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup; 120 private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
121 121
122 /// <summary> 122 /// <summary>
123 /// A reference to an object that indicates whatever the 123 /// A reference to an object that indicates whatever the
124 /// SmartThreadPool has been canceled 124 /// SmartThreadPool has been canceled
125 /// </summary> 125 /// </summary>
126 private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup; 126 private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
@@ -197,7 +197,7 @@ namespace Amib.Threading.Internal
197 /// <param name="workItemInfo">The WorkItemInfo of te workitem</param> 197 /// <param name="workItemInfo">The WorkItemInfo of te workitem</param>
198 /// <param name="callback">Callback delegate for the callback.</param> 198 /// <param name="callback">Callback delegate for the callback.</param>
199 /// <param name="state">State with which to call the callback delegate.</param> 199 /// <param name="state">State with which to call the callback delegate.</param>
200 /// 200 ///
201 /// We assume that the WorkItem object is created within the thread 201 /// We assume that the WorkItem object is created within the thread
202 /// that meant to run the callback 202 /// that meant to run the callback
203 public WorkItem( 203 public WorkItem(
@@ -402,7 +402,7 @@ namespace Amib.Threading.Internal
402 { 402 {
403 tae.GetHashCode(); 403 tae.GetHashCode();
404 // Check if the work item was cancelled 404 // Check if the work item was cancelled
405 // If we got a ThreadAbortException and the STP is not shutting down, it means the 405 // If we got a ThreadAbortException and the STP is not shutting down, it means the
406 // work items was cancelled. 406 // work items was cancelled.
407 if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown) 407 if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown)
408 { 408 {
@@ -471,7 +471,7 @@ namespace Amib.Threading.Internal
471 /// <param name="waitableResults">Array of work item result objects</param> 471 /// <param name="waitableResults">Array of work item result objects</param>
472 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 472 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
473 /// <param name="exitContext"> 473 /// <param name="exitContext">
474 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 474 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
475 /// </param> 475 /// </param>
476 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 476 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
477 /// <returns> 477 /// <returns>
@@ -553,7 +553,7 @@ namespace Amib.Threading.Internal
553 /// <param name="waitableResults">Array of work item result objects</param> 553 /// <param name="waitableResults">Array of work item result objects</param>
554 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param> 554 /// <param name="millisecondsTimeout">The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.</param>
555 /// <param name="exitContext"> 555 /// <param name="exitContext">
556 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false. 556 /// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
557 /// </param> 557 /// </param>
558 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param> 558 /// <param name="cancelWaitHandle">A cancel wait handle to interrupt the wait if needed</param>
559 /// <returns> 559 /// <returns>
@@ -734,7 +734,7 @@ namespace Amib.Threading.Internal
734 // so it already signaled its completion. 734 // so it already signaled its completion.
735 //signalComplete = true; 735 //signalComplete = true;
736 } 736 }
737 } 737 }
738 success = true; 738 success = true;
739 break; 739 break;
740 case WorkItemState.Completed: 740 case WorkItemState.Completed:
@@ -856,7 +856,7 @@ namespace Amib.Threading.Internal
856 { 856 {
857 case 0: 857 case 0:
858 // The work item signaled 858 // The work item signaled
859 // Note that the signal could be also as a result of canceling the 859 // Note that the signal could be also as a result of canceling the
860 // work item (not the get result) 860 // work item (not the get result)
861 break; 861 break;
862 case 1: 862 case 1:
@@ -884,7 +884,7 @@ namespace Amib.Threading.Internal
884 } 884 }
885 885
886 /// <summary> 886 /// <summary>
887 /// A wait handle to wait for completion, cancel, or timeout 887 /// A wait handle to wait for completion, cancel, or timeout
888 /// </summary> 888 /// </summary>
889 private WaitHandle GetWaitHandle() 889 private WaitHandle GetWaitHandle()
890 { 890 {
diff --git a/ThirdParty/SmartThreadPool/WorkItemFactory.cs b/ThirdParty/SmartThreadPool/WorkItemFactory.cs
index 16ccd81..471eb20 100644
--- a/ThirdParty/SmartThreadPool/WorkItemFactory.cs
+++ b/ThirdParty/SmartThreadPool/WorkItemFactory.cs
@@ -2,146 +2,146 @@ using System;
2 2
3namespace Amib.Threading.Internal 3namespace Amib.Threading.Internal
4{ 4{
5 #region WorkItemFactory class 5 #region WorkItemFactory class
6 6
7 public class WorkItemFactory 7 public class WorkItemFactory
8 { 8 {
9 /// <summary> 9 /// <summary>
10 /// Create a new work item 10 /// Create a new work item
11 /// </summary> 11 /// </summary>
12 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
13 /// <param name="wigStartInfo">Work item group start information</param>
14 /// <param name="callback">A callback to execute</param>
15 /// <returns>Returns a work item</returns>
16 public static WorkItem CreateWorkItem(
17 IWorkItemsGroup workItemsGroup,
18 WIGStartInfo wigStartInfo,
19 WorkItemCallback callback)
20 {
21 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
22 }
23
24 /// <summary>
25 /// Create a new work item
26 /// </summary>
27 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param> 12 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
28 /// <param name="wigStartInfo">Work item group start information</param> 13 /// <param name="wigStartInfo">Work item group start information</param>
29 /// <param name="callback">A callback to execute</param> 14 /// <param name="callback">A callback to execute</param>
30 /// <param name="workItemPriority">The priority of the work item</param> 15 /// <returns>Returns a work item</returns>
31 /// <returns>Returns a work item</returns> 16 public static WorkItem CreateWorkItem(
32 public static WorkItem CreateWorkItem( 17 IWorkItemsGroup workItemsGroup,
33 IWorkItemsGroup workItemsGroup, 18 WIGStartInfo wigStartInfo,
34 WIGStartInfo wigStartInfo, 19 WorkItemCallback callback)
35 WorkItemCallback callback, 20 {
36 WorkItemPriority workItemPriority) 21 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
37 { 22 }
38 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority); 23
39 } 24 /// <summary>
40 25 /// Create a new work item
41 /// <summary> 26 /// </summary>
42 /// Create a new work item
43 /// </summary>
44 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param> 27 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
45 /// <param name="wigStartInfo">Work item group start information</param> 28 /// <param name="wigStartInfo">Work item group start information</param>
46 /// <param name="workItemInfo">Work item info</param> 29 /// <param name="callback">A callback to execute</param>
47 /// <param name="callback">A callback to execute</param> 30 /// <param name="workItemPriority">The priority of the work item</param>
48 /// <returns>Returns a work item</returns> 31 /// <returns>Returns a work item</returns>
49 public static WorkItem CreateWorkItem( 32 public static WorkItem CreateWorkItem(
50 IWorkItemsGroup workItemsGroup, 33 IWorkItemsGroup workItemsGroup,
51 WIGStartInfo wigStartInfo, 34 WIGStartInfo wigStartInfo,
52 WorkItemInfo workItemInfo, 35 WorkItemCallback callback,
53 WorkItemCallback callback) 36 WorkItemPriority workItemPriority)
54 { 37 {
55 return CreateWorkItem( 38 return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
56 workItemsGroup, 39 }
57 wigStartInfo, 40
58 workItemInfo, 41 /// <summary>
59 callback, 42 /// Create a new work item
60 null); 43 /// </summary>
61 }
62
63 /// <summary>
64 /// Create a new work item
65 /// </summary>
66 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param> 44 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
67 /// <param name="wigStartInfo">Work item group start information</param> 45 /// <param name="wigStartInfo">Work item group start information</param>
68 /// <param name="callback">A callback to execute</param> 46 /// <param name="workItemInfo">Work item info</param>
69 /// <param name="state"> 47 /// <param name="callback">A callback to execute</param>
70 /// The context object of the work item. Used for passing arguments to the work item. 48 /// <returns>Returns a work item</returns>
71 /// </param> 49 public static WorkItem CreateWorkItem(
72 /// <returns>Returns a work item</returns> 50 IWorkItemsGroup workItemsGroup,
73 public static WorkItem CreateWorkItem( 51 WIGStartInfo wigStartInfo,
74 IWorkItemsGroup workItemsGroup, 52 WorkItemInfo workItemInfo,
75 WIGStartInfo wigStartInfo, 53 WorkItemCallback callback)
76 WorkItemCallback callback, 54 {
77 object state) 55 return CreateWorkItem(
78 { 56 workItemsGroup,
79 ValidateCallback(callback); 57 wigStartInfo,
80 58 workItemInfo,
81 WorkItemInfo workItemInfo = new WorkItemInfo(); 59 callback,
82 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; 60 null);
83 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; 61 }
84 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback; 62
85 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; 63 /// <summary>
86 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; 64 /// Create a new work item
65 /// </summary>
66 /// <param name="workItemsGroup">The WorkItemsGroup of this workitem</param>
67 /// <param name="wigStartInfo">Work item group start information</param>
68 /// <param name="callback">A callback to execute</param>
69 /// <param name="state">
70 /// The context object of the work item. Used for passing arguments to the work item.
71 /// </param>
72 /// <returns>Returns a work item</returns>
73 public static WorkItem CreateWorkItem(
74 IWorkItemsGroup workItemsGroup,
75 WIGStartInfo wigStartInfo,
76 WorkItemCallback callback,
77 object state)
78 {
79 ValidateCallback(callback);
80
81 WorkItemInfo workItemInfo = new WorkItemInfo();
82 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
83 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
84 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
85 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
86 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
87 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority; 87 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
88 88
89 WorkItem workItem = new WorkItem( 89 WorkItem workItem = new WorkItem(
90 workItemsGroup, 90 workItemsGroup,
91 workItemInfo, 91 workItemInfo,
92 callback, 92 callback,
93 state); 93 state);
94 return workItem; 94 return workItem;
95 } 95 }
96 96
97 /// <summary> 97 /// <summary>
98 /// Create a new work item 98 /// Create a new work item
99 /// </summary> 99 /// </summary>
100 /// <param name="workItemsGroup">The work items group</param>
101 /// <param name="wigStartInfo">Work item group start information</param>
102 /// <param name="callback">A callback to execute</param>
103 /// <param name="state">
104 /// The context object of the work item. Used for passing arguments to the work item.
105 /// </param>
106 /// <param name="workItemPriority">The work item priority</param>
107 /// <returns>Returns a work item</returns>
108 public static WorkItem CreateWorkItem(
109 IWorkItemsGroup workItemsGroup,
110 WIGStartInfo wigStartInfo,
111 WorkItemCallback callback,
112 object state,
113 WorkItemPriority workItemPriority)
114 {
115 ValidateCallback(callback);
116
117 WorkItemInfo workItemInfo = new WorkItemInfo();
118 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
119 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
120 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
121 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
122 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
123 workItemInfo.WorkItemPriority = workItemPriority;
124
125 WorkItem workItem = new WorkItem(
126 workItemsGroup,
127 workItemInfo,
128 callback,
129 state);
130
131 return workItem;
132 }
133
134 /// <summary>
135 /// Create a new work item
136 /// </summary>
137 /// <param name="workItemsGroup">The work items group</param> 100 /// <param name="workItemsGroup">The work items group</param>
138 /// <param name="wigStartInfo">Work item group start information</param> 101 /// <param name="wigStartInfo">Work item group start information</param>
139 /// <param name="workItemInfo">Work item information</param> 102 /// <param name="callback">A callback to execute</param>
140 /// <param name="callback">A callback to execute</param> 103 /// <param name="state">
141 /// <param name="state"> 104 /// The context object of the work item. Used for passing arguments to the work item.
142 /// The context object of the work item. Used for passing arguments to the work item. 105 /// </param>
143 /// </param> 106 /// <param name="workItemPriority">The work item priority</param>
144 /// <returns>Returns a work item</returns> 107 /// <returns>Returns a work item</returns>
108 public static WorkItem CreateWorkItem(
109 IWorkItemsGroup workItemsGroup,
110 WIGStartInfo wigStartInfo,
111 WorkItemCallback callback,
112 object state,
113 WorkItemPriority workItemPriority)
114 {
115 ValidateCallback(callback);
116
117 WorkItemInfo workItemInfo = new WorkItemInfo();
118 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
119 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
120 workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
121 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
122 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
123 workItemInfo.WorkItemPriority = workItemPriority;
124
125 WorkItem workItem = new WorkItem(
126 workItemsGroup,
127 workItemInfo,
128 callback,
129 state);
130
131 return workItem;
132 }
133
134 /// <summary>
135 /// Create a new work item
136 /// </summary>
137 /// <param name="workItemsGroup">The work items group</param>
138 /// <param name="wigStartInfo">Work item group start information</param>
139 /// <param name="workItemInfo">Work item information</param>
140 /// <param name="callback">A callback to execute</param>
141 /// <param name="state">
142 /// The context object of the work item. Used for passing arguments to the work item.
143 /// </param>
144 /// <returns>Returns a work item</returns>
145 public static WorkItem CreateWorkItem( 145 public static WorkItem CreateWorkItem(
146 IWorkItemsGroup workItemsGroup, 146 IWorkItemsGroup workItemsGroup,
147 WIGStartInfo wigStartInfo, 147 WIGStartInfo wigStartInfo,
@@ -161,183 +161,183 @@ namespace Amib.Threading.Internal
161 return workItem; 161 return workItem;
162 } 162 }
163 163
164 /// <summary> 164 /// <summary>
165 /// Create a new work item 165 /// Create a new work item
166 /// </summary> 166 /// </summary>
167 /// <param name="workItemsGroup">The work items group</param> 167 /// <param name="workItemsGroup">The work items group</param>
168 /// <param name="wigStartInfo">Work item group start information</param> 168 /// <param name="wigStartInfo">Work item group start information</param>
169 /// <param name="callback">A callback to execute</param> 169 /// <param name="callback">A callback to execute</param>
170 /// <param name="state"> 170 /// <param name="state">
171 /// The context object of the work item. Used for passing arguments to the work item. 171 /// The context object of the work item. Used for passing arguments to the work item.
172 /// </param> 172 /// </param>
173 /// <param name="postExecuteWorkItemCallback"> 173 /// <param name="postExecuteWorkItemCallback">
174 /// A delegate to call after the callback completion 174 /// A delegate to call after the callback completion
175 /// </param> 175 /// </param>
176 /// <returns>Returns a work item</returns> 176 /// <returns>Returns a work item</returns>
177 public static WorkItem CreateWorkItem( 177 public static WorkItem CreateWorkItem(
178 IWorkItemsGroup workItemsGroup, 178 IWorkItemsGroup workItemsGroup,
179 WIGStartInfo wigStartInfo, 179 WIGStartInfo wigStartInfo,
180 WorkItemCallback callback, 180 WorkItemCallback callback,
181 object state, 181 object state,
182 PostExecuteWorkItemCallback postExecuteWorkItemCallback) 182 PostExecuteWorkItemCallback postExecuteWorkItemCallback)
183 { 183 {
184 ValidateCallback(callback); 184 ValidateCallback(callback);
185 ValidateCallback(postExecuteWorkItemCallback); 185 ValidateCallback(postExecuteWorkItemCallback);
186 186
187 WorkItemInfo workItemInfo = new WorkItemInfo(); 187 WorkItemInfo workItemInfo = new WorkItemInfo();
188 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; 188 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
189 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; 189 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
190 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; 190 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
191 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; 191 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
192 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; 192 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
193 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority; 193 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
194 194
195 WorkItem workItem = new WorkItem( 195 WorkItem workItem = new WorkItem(
196 workItemsGroup, 196 workItemsGroup,
197 workItemInfo, 197 workItemInfo,
198 callback, 198 callback,
199 state); 199 state);
200 200
201 return workItem; 201 return workItem;
202 } 202 }
203 203
204 /// <summary> 204 /// <summary>
205 /// Create a new work item 205 /// Create a new work item
206 /// </summary> 206 /// </summary>
207 /// <param name="workItemsGroup">The work items group</param> 207 /// <param name="workItemsGroup">The work items group</param>
208 /// <param name="wigStartInfo">Work item group start information</param> 208 /// <param name="wigStartInfo">Work item group start information</param>
209 /// <param name="callback">A callback to execute</param> 209 /// <param name="callback">A callback to execute</param>
210 /// <param name="state"> 210 /// <param name="state">
211 /// The context object of the work item. Used for passing arguments to the work item. 211 /// The context object of the work item. Used for passing arguments to the work item.
212 /// </param> 212 /// </param>
213 /// <param name="postExecuteWorkItemCallback"> 213 /// <param name="postExecuteWorkItemCallback">
214 /// A delegate to call after the callback completion 214 /// A delegate to call after the callback completion
215 /// </param> 215 /// </param>
216 /// <param name="workItemPriority">The work item priority</param> 216 /// <param name="workItemPriority">The work item priority</param>
217 /// <returns>Returns a work item</returns> 217 /// <returns>Returns a work item</returns>
218 public static WorkItem CreateWorkItem( 218 public static WorkItem CreateWorkItem(
219 IWorkItemsGroup workItemsGroup, 219 IWorkItemsGroup workItemsGroup,
220 WIGStartInfo wigStartInfo, 220 WIGStartInfo wigStartInfo,
221 WorkItemCallback callback, 221 WorkItemCallback callback,
222 object state, 222 object state,
223 PostExecuteWorkItemCallback postExecuteWorkItemCallback, 223 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
224 WorkItemPriority workItemPriority) 224 WorkItemPriority workItemPriority)
225 { 225 {
226 ValidateCallback(callback); 226 ValidateCallback(callback);
227 ValidateCallback(postExecuteWorkItemCallback); 227 ValidateCallback(postExecuteWorkItemCallback);
228 228
229 WorkItemInfo workItemInfo = new WorkItemInfo(); 229 WorkItemInfo workItemInfo = new WorkItemInfo();
230 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; 230 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
231 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; 231 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
232 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; 232 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
233 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute; 233 workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
234 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; 234 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
235 workItemInfo.WorkItemPriority = workItemPriority; 235 workItemInfo.WorkItemPriority = workItemPriority;
236 236
237 WorkItem workItem = new WorkItem( 237 WorkItem workItem = new WorkItem(
238 workItemsGroup, 238 workItemsGroup,
239 workItemInfo, 239 workItemInfo,
240 callback, 240 callback,
241 state); 241 state);
242 242
243 return workItem; 243 return workItem;
244 } 244 }
245 245
246 /// <summary> 246 /// <summary>
247 /// Create a new work item 247 /// Create a new work item
248 /// </summary> 248 /// </summary>
249 /// <param name="workItemsGroup">The work items group</param> 249 /// <param name="workItemsGroup">The work items group</param>
250 /// <param name="wigStartInfo">Work item group start information</param> 250 /// <param name="wigStartInfo">Work item group start information</param>
251 /// <param name="callback">A callback to execute</param> 251 /// <param name="callback">A callback to execute</param>
252 /// <param name="state"> 252 /// <param name="state">
253 /// The context object of the work item. Used for passing arguments to the work item. 253 /// The context object of the work item. Used for passing arguments to the work item.
254 /// </param> 254 /// </param>
255 /// <param name="postExecuteWorkItemCallback"> 255 /// <param name="postExecuteWorkItemCallback">
256 /// A delegate to call after the callback completion 256 /// A delegate to call after the callback completion
257 /// </param> 257 /// </param>
258 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> 258 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
259 /// <returns>Returns a work item</returns> 259 /// <returns>Returns a work item</returns>
260 public static WorkItem CreateWorkItem( 260 public static WorkItem CreateWorkItem(
261 IWorkItemsGroup workItemsGroup, 261 IWorkItemsGroup workItemsGroup,
262 WIGStartInfo wigStartInfo, 262 WIGStartInfo wigStartInfo,
263 WorkItemCallback callback, 263 WorkItemCallback callback,
264 object state, 264 object state,
265 PostExecuteWorkItemCallback postExecuteWorkItemCallback, 265 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
266 CallToPostExecute callToPostExecute) 266 CallToPostExecute callToPostExecute)
267 { 267 {
268 ValidateCallback(callback); 268 ValidateCallback(callback);
269 ValidateCallback(postExecuteWorkItemCallback); 269 ValidateCallback(postExecuteWorkItemCallback);
270 270
271 WorkItemInfo workItemInfo = new WorkItemInfo(); 271 WorkItemInfo workItemInfo = new WorkItemInfo();
272 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; 272 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
273 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; 273 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
274 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; 274 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
275 workItemInfo.CallToPostExecute = callToPostExecute; 275 workItemInfo.CallToPostExecute = callToPostExecute;
276 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; 276 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
277 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority; 277 workItemInfo.WorkItemPriority = wigStartInfo.WorkItemPriority;
278 278
279 WorkItem workItem = new WorkItem( 279 WorkItem workItem = new WorkItem(
280 workItemsGroup, 280 workItemsGroup,
281 workItemInfo, 281 workItemInfo,
282 callback, 282 callback,
283 state); 283 state);
284 284
285 return workItem; 285 return workItem;
286 } 286 }
287 287
288 /// <summary> 288 /// <summary>
289 /// Create a new work item 289 /// Create a new work item
290 /// </summary> 290 /// </summary>
291 /// <param name="workItemsGroup">The work items group</param> 291 /// <param name="workItemsGroup">The work items group</param>
292 /// <param name="wigStartInfo">Work item group start information</param> 292 /// <param name="wigStartInfo">Work item group start information</param>
293 /// <param name="callback">A callback to execute</param> 293 /// <param name="callback">A callback to execute</param>
294 /// <param name="state"> 294 /// <param name="state">
295 /// The context object of the work item. Used for passing arguments to the work item. 295 /// The context object of the work item. Used for passing arguments to the work item.
296 /// </param> 296 /// </param>
297 /// <param name="postExecuteWorkItemCallback"> 297 /// <param name="postExecuteWorkItemCallback">
298 /// A delegate to call after the callback completion 298 /// A delegate to call after the callback completion
299 /// </param> 299 /// </param>
300 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param> 300 /// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
301 /// <param name="workItemPriority">The work item priority</param> 301 /// <param name="workItemPriority">The work item priority</param>
302 /// <returns>Returns a work item</returns> 302 /// <returns>Returns a work item</returns>
303 public static WorkItem CreateWorkItem( 303 public static WorkItem CreateWorkItem(
304 IWorkItemsGroup workItemsGroup, 304 IWorkItemsGroup workItemsGroup,
305 WIGStartInfo wigStartInfo, 305 WIGStartInfo wigStartInfo,
306 WorkItemCallback callback, 306 WorkItemCallback callback,
307 object state, 307 object state,
308 PostExecuteWorkItemCallback postExecuteWorkItemCallback, 308 PostExecuteWorkItemCallback postExecuteWorkItemCallback,
309 CallToPostExecute callToPostExecute, 309 CallToPostExecute callToPostExecute,
310 WorkItemPriority workItemPriority) 310 WorkItemPriority workItemPriority)
311 { 311 {
312 312
313 ValidateCallback(callback); 313 ValidateCallback(callback);
314 ValidateCallback(postExecuteWorkItemCallback); 314 ValidateCallback(postExecuteWorkItemCallback);
315 315
316 WorkItemInfo workItemInfo = new WorkItemInfo(); 316 WorkItemInfo workItemInfo = new WorkItemInfo();
317 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext; 317 workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
318 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext; 318 workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
319 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback; 319 workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
320 workItemInfo.CallToPostExecute = callToPostExecute; 320 workItemInfo.CallToPostExecute = callToPostExecute;
321 workItemInfo.WorkItemPriority = workItemPriority; 321 workItemInfo.WorkItemPriority = workItemPriority;
322 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects; 322 workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
323 323
324 WorkItem workItem = new WorkItem( 324 WorkItem workItem = new WorkItem(
325 workItemsGroup, 325 workItemsGroup,
326 workItemInfo, 326 workItemInfo,
327 callback, 327 callback,
328 state); 328 state);
329 329
330 return workItem; 330 return workItem;
331 } 331 }
332 332
333 private static void ValidateCallback(Delegate callback) 333 private static void ValidateCallback(Delegate callback)
334 { 334 {
335 if (callback != null && callback.GetInvocationList().Length > 1) 335 if (callback != null && callback.GetInvocationList().Length > 1)
336 { 336 {
337 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains"); 337 throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
338 } 338 }
339 } 339 }
340 } 340 }
341 341
342 #endregion 342 #endregion
343} 343}
diff --git a/ThirdParty/SmartThreadPool/WorkItemInfo.cs b/ThirdParty/SmartThreadPool/WorkItemInfo.cs
index 0d7fc85..5be82a2 100644
--- a/ThirdParty/SmartThreadPool/WorkItemInfo.cs
+++ b/ThirdParty/SmartThreadPool/WorkItemInfo.cs
@@ -1,69 +1,69 @@
1namespace Amib.Threading 1namespace Amib.Threading
2{ 2{
3 #region WorkItemInfo class 3 #region WorkItemInfo class
4 4
5 /// <summary> 5 /// <summary>
6 /// Summary description for WorkItemInfo. 6 /// Summary description for WorkItemInfo.
7 /// </summary> 7 /// </summary>
8 public class WorkItemInfo 8 public class WorkItemInfo
9 { 9 {
10 public WorkItemInfo() 10 public WorkItemInfo()
11 { 11 {
12 UseCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext; 12 UseCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
13 UseCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext; 13 UseCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
14 DisposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects; 14 DisposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
15 CallToPostExecute = SmartThreadPool.DefaultCallToPostExecute; 15 CallToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
16 PostExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback; 16 PostExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
17 WorkItemPriority = SmartThreadPool.DefaultWorkItemPriority; 17 WorkItemPriority = SmartThreadPool.DefaultWorkItemPriority;
18 } 18 }
19 19
20 public WorkItemInfo(WorkItemInfo workItemInfo) 20 public WorkItemInfo(WorkItemInfo workItemInfo)
21 { 21 {
22 UseCallerCallContext = workItemInfo.UseCallerCallContext; 22 UseCallerCallContext = workItemInfo.UseCallerCallContext;
23 UseCallerHttpContext = workItemInfo.UseCallerHttpContext; 23 UseCallerHttpContext = workItemInfo.UseCallerHttpContext;
24 DisposeOfStateObjects = workItemInfo.DisposeOfStateObjects; 24 DisposeOfStateObjects = workItemInfo.DisposeOfStateObjects;
25 CallToPostExecute = workItemInfo.CallToPostExecute; 25 CallToPostExecute = workItemInfo.CallToPostExecute;
26 PostExecuteWorkItemCallback = workItemInfo.PostExecuteWorkItemCallback; 26 PostExecuteWorkItemCallback = workItemInfo.PostExecuteWorkItemCallback;
27 WorkItemPriority = workItemInfo.WorkItemPriority; 27 WorkItemPriority = workItemInfo.WorkItemPriority;
28 Timeout = workItemInfo.Timeout; 28 Timeout = workItemInfo.Timeout;
29 } 29 }
30 30
31 /// <summary> 31 /// <summary>
32 /// Get/Set if to use the caller's security context 32 /// Get/Set if to use the caller's security context
33 /// </summary> 33 /// </summary>
34 public bool UseCallerCallContext { get; set; } 34 public bool UseCallerCallContext { get; set; }
35 35
36 /// <summary> 36 /// <summary>
37 /// Get/Set if to use the caller's HTTP context 37 /// Get/Set if to use the caller's HTTP context
38 /// </summary> 38 /// </summary>
39 public bool UseCallerHttpContext { get; set; } 39 public bool UseCallerHttpContext { get; set; }
40 40
41 /// <summary> 41 /// <summary>
42 /// Get/Set if to dispose of the state object of a work item 42 /// Get/Set if to dispose of the state object of a work item
43 /// </summary> 43 /// </summary>
44 public bool DisposeOfStateObjects { get; set; } 44 public bool DisposeOfStateObjects { get; set; }
45 45
46 /// <summary> 46 /// <summary>
47 /// Get/Set the run the post execute options 47 /// Get/Set the run the post execute options
48 /// </summary> 48 /// </summary>
49 public CallToPostExecute CallToPostExecute { get; set; } 49 public CallToPostExecute CallToPostExecute { get; set; }
50 50
51 /// <summary> 51 /// <summary>
52 /// Get/Set the post execute callback 52 /// Get/Set the post execute callback
53 /// </summary> 53 /// </summary>
54 public PostExecuteWorkItemCallback PostExecuteWorkItemCallback { get; set; } 54 public PostExecuteWorkItemCallback PostExecuteWorkItemCallback { get; set; }
55 55
56 /// <summary> 56 /// <summary>
57 /// Get/Set the work item's priority 57 /// Get/Set the work item's priority
58 /// </summary> 58 /// </summary>
59 public WorkItemPriority WorkItemPriority { get; set; } 59 public WorkItemPriority WorkItemPriority { get; set; }
60 60
61 /// <summary> 61 /// <summary>
62 /// Get/Set the work item's timout in milliseconds. 62 /// Get/Set the work item's timout in milliseconds.
63 /// This is a passive timout. When the timout expires the work item won't be actively aborted! 63 /// This is a passive timout. When the timout expires the work item won't be actively aborted!
64 /// </summary> 64 /// </summary>
65 public long Timeout { get; set; } 65 public long Timeout { get; set; }
66 } 66 }
67 67
68 #endregion 68 #endregion
69} 69}
diff --git a/ThirdParty/SmartThreadPool/WorkItemsGroup.cs b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs
index d9d34ac..d429bc6 100644
--- a/ThirdParty/SmartThreadPool/WorkItemsGroup.cs
+++ b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs
@@ -6,107 +6,107 @@ using System.Diagnostics;
6namespace Amib.Threading.Internal 6namespace Amib.Threading.Internal
7{ 7{
8 8
9 #region WorkItemsGroup class 9 #region WorkItemsGroup class
10 10
11 /// <summary> 11 /// <summary>
12 /// Summary description for WorkItemsGroup. 12 /// Summary description for WorkItemsGroup.
13 /// </summary> 13 /// </summary>
14 public class WorkItemsGroup : WorkItemsGroupBase 14 public class WorkItemsGroup : WorkItemsGroupBase
15 { 15 {
16 #region Private members 16 #region Private members
17 17
18 private readonly object _lock = new object(); 18 private readonly object _lock = new object();
19 19
20 /// <summary> 20 /// <summary>
21 /// A reference to the SmartThreadPool instance that created this 21 /// A reference to the SmartThreadPool instance that created this
22 /// WorkItemsGroup. 22 /// WorkItemsGroup.
23 /// </summary> 23 /// </summary>
24 private readonly SmartThreadPool _stp; 24 private readonly SmartThreadPool _stp;
25 25
26 /// <summary> 26 /// <summary>
27 /// The OnIdle event 27 /// The OnIdle event
28 /// </summary> 28 /// </summary>
29 private event WorkItemsGroupIdleHandler _onIdle; 29 private event WorkItemsGroupIdleHandler _onIdle;
30 30
31 /// <summary> 31 /// <summary>
32 /// A flag to indicate if the Work Items Group is now suspended. 32 /// A flag to indicate if the Work Items Group is now suspended.
33 /// </summary> 33 /// </summary>
34 private bool _isSuspended; 34 private bool _isSuspended;
35 35
36 /// <summary> 36 /// <summary>
37 /// Defines how many work items of this WorkItemsGroup can run at once. 37 /// Defines how many work items of this WorkItemsGroup can run at once.
38 /// </summary> 38 /// </summary>
39 private int _concurrency; 39 private int _concurrency;
40 40
41 /// <summary> 41 /// <summary>
42 /// Priority queue to hold work items before they are passed 42 /// Priority queue to hold work items before they are passed
43 /// to the SmartThreadPool. 43 /// to the SmartThreadPool.
44 /// </summary> 44 /// </summary>
45 private readonly PriorityQueue _workItemsQueue; 45 private readonly PriorityQueue _workItemsQueue;
46 46
47 /// <summary> 47 /// <summary>
48 /// Indicate how many work items are waiting in the SmartThreadPool 48 /// Indicate how many work items are waiting in the SmartThreadPool
49 /// queue. 49 /// queue.
50 /// This value is used to apply the concurrency. 50 /// This value is used to apply the concurrency.
51 /// </summary> 51 /// </summary>
52 private int _workItemsInStpQueue; 52 private int _workItemsInStpQueue;
53 53
54 /// <summary> 54 /// <summary>
55 /// Indicate how many work items are currently running in the SmartThreadPool. 55 /// Indicate how many work items are currently running in the SmartThreadPool.
56 /// This value is used with the Cancel, to calculate if we can send new 56 /// This value is used with the Cancel, to calculate if we can send new
57 /// work items to the STP. 57 /// work items to the STP.
58 /// </summary> 58 /// </summary>
59 private int _workItemsExecutingInStp = 0; 59 private int _workItemsExecutingInStp = 0;
60 60
61 /// <summary> 61 /// <summary>
62 /// WorkItemsGroup start information 62 /// WorkItemsGroup start information
63 /// </summary> 63 /// </summary>
64 private readonly WIGStartInfo _workItemsGroupStartInfo; 64 private readonly WIGStartInfo _workItemsGroupStartInfo;
65 65
66 /// <summary> 66 /// <summary>
67 /// Signaled when all of the WorkItemsGroup's work item completed. 67 /// Signaled when all of the WorkItemsGroup's work item completed.
68 /// </summary> 68 /// </summary>
69 //private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true); 69 //private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
70 private readonly ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true); 70 private readonly ManualResetEvent _isIdleWaitHandle = EventWaitHandleFactory.CreateManualResetEvent(true);
71 71
72 /// <summary> 72 /// <summary>
73 /// A common object for all the work items that this work items group 73 /// A common object for all the work items that this work items group
74 /// generate so we can mark them to cancel in O(1) 74 /// generate so we can mark them to cancel in O(1)
75 /// </summary> 75 /// </summary>
76 private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup(); 76 private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
77 77
78 #endregion 78 #endregion
79 79
80 #region Construction 80 #region Construction
81 81
82 public WorkItemsGroup( 82 public WorkItemsGroup(
83 SmartThreadPool stp, 83 SmartThreadPool stp,
84 int concurrency, 84 int concurrency,
85 WIGStartInfo wigStartInfo) 85 WIGStartInfo wigStartInfo)
86 { 86 {
87 if (concurrency <= 0) 87 if (concurrency <= 0)
88 { 88 {
89 throw new ArgumentOutOfRangeException( 89 throw new ArgumentOutOfRangeException(
90 "concurrency", 90 "concurrency",
91#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) 91#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
92 concurrency, 92 concurrency,
93#endif 93#endif
94 "concurrency must be greater than zero"); 94 "concurrency must be greater than zero");
95 } 95 }
96 _stp = stp; 96 _stp = stp;
97 _concurrency = concurrency; 97 _concurrency = concurrency;
98 _workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo).AsReadOnly(); 98 _workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo).AsReadOnly();
99 _workItemsQueue = new PriorityQueue(); 99 _workItemsQueue = new PriorityQueue();
100 Name = "WorkItemsGroup"; 100 Name = "WorkItemsGroup";
101 101
102 // The _workItemsInStpQueue gets the number of currently executing work items, 102 // The _workItemsInStpQueue gets the number of currently executing work items,
103 // because once a work item is executing, it cannot be cancelled. 103 // because once a work item is executing, it cannot be cancelled.
104 _workItemsInStpQueue = _workItemsExecutingInStp; 104 _workItemsInStpQueue = _workItemsExecutingInStp;
105 105
106 _isSuspended = _workItemsGroupStartInfo.StartSuspended; 106 _isSuspended = _workItemsGroupStartInfo.StartSuspended;
107 } 107 }
108 108
109 #endregion 109 #endregion
110 110
111 #region WorkItemsGroupBase Overrides 111 #region WorkItemsGroupBase Overrides
112 112
@@ -146,7 +146,7 @@ namespace Amib.Threading.Internal
146 } 146 }
147 } 147 }
148 148
149 /// <summary> 149 /// <summary>
150 /// WorkItemsGroup start information 150 /// WorkItemsGroup start information
151 /// </summary> 151 /// </summary>
152 public override WIGStartInfo WIGStartInfo 152 public override WIGStartInfo WIGStartInfo
@@ -154,38 +154,38 @@ namespace Amib.Threading.Internal
154 get { return _workItemsGroupStartInfo; } 154 get { return _workItemsGroupStartInfo; }
155 } 155 }
156 156
157 /// <summary> 157 /// <summary>
158 /// Start the Work Items Group if it was started suspended 158 /// Start the Work Items Group if it was started suspended
159 /// </summary> 159 /// </summary>
160 public override void Start() 160 public override void Start()
161 { 161 {
162 // If the Work Items Group already started then quit 162 // If the Work Items Group already started then quit
163 if (!_isSuspended) 163 if (!_isSuspended)
164 { 164 {
165 return; 165 return;
166 } 166 }
167 _isSuspended = false; 167 _isSuspended = false;
168 168
169 EnqueueToSTPNextNWorkItem(Math.Min(_workItemsQueue.Count, _concurrency)); 169 EnqueueToSTPNextNWorkItem(Math.Min(_workItemsQueue.Count, _concurrency));
170 } 170 }
171 171
172 public override void Cancel(bool abortExecution) 172 public override void Cancel(bool abortExecution)
173 { 173 {
174 lock (_lock) 174 lock (_lock)
175 { 175 {
176 _canceledWorkItemsGroup.IsCanceled = true; 176 _canceledWorkItemsGroup.IsCanceled = true;
177 _workItemsQueue.Clear(); 177 _workItemsQueue.Clear();
178 _workItemsInStpQueue = 0; 178 _workItemsInStpQueue = 0;
179 _canceledWorkItemsGroup = new CanceledWorkItemsGroup(); 179 _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
180 } 180 }
181 181
182 if (abortExecution) 182 if (abortExecution)
183 { 183 {
184 _stp.CancelAbortWorkItemsGroup(this); 184 _stp.CancelAbortWorkItemsGroup(this);
185 } 185 }
186 } 186 }
187 187
188 /// <summary> 188 /// <summary>
189 /// Wait for the thread pool to be idle 189 /// Wait for the thread pool to be idle
190 /// </summary> 190 /// </summary>
191 public override bool WaitForIdle(int millisecondsTimeout) 191 public override bool WaitForIdle(int millisecondsTimeout)
@@ -194,34 +194,34 @@ namespace Amib.Threading.Internal
194 return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false); 194 return STPEventWaitHandle.WaitOne(_isIdleWaitHandle, millisecondsTimeout, false);
195 } 195 }
196 196
197 public override event WorkItemsGroupIdleHandler OnIdle 197 public override event WorkItemsGroupIdleHandler OnIdle
198 { 198 {
199 add { _onIdle += value; } 199 add { _onIdle += value; }
200 remove { _onIdle -= value; } 200 remove { _onIdle -= value; }
201 } 201 }
202 202
203 #endregion 203 #endregion
204 204
205 #region Private methods 205 #region Private methods
206 206
207 private void RegisterToWorkItemCompletion(IWorkItemResult wir) 207 private void RegisterToWorkItemCompletion(IWorkItemResult wir)
208 { 208 {
209 IInternalWorkItemResult iwir = (IInternalWorkItemResult)wir; 209 IInternalWorkItemResult iwir = (IInternalWorkItemResult)wir;
210 iwir.OnWorkItemStarted += OnWorkItemStartedCallback; 210 iwir.OnWorkItemStarted += OnWorkItemStartedCallback;
211 iwir.OnWorkItemCompleted += OnWorkItemCompletedCallback; 211 iwir.OnWorkItemCompleted += OnWorkItemCompletedCallback;
212 } 212 }
213 213
214 public void OnSTPIsStarting() 214 public void OnSTPIsStarting()
215 { 215 {
216 if (_isSuspended) 216 if (_isSuspended)
217 { 217 {
218 return; 218 return;
219 } 219 }
220 220
221 EnqueueToSTPNextNWorkItem(_concurrency); 221 EnqueueToSTPNextNWorkItem(_concurrency);
222 } 222 }
223 223
224 public void EnqueueToSTPNextNWorkItem(int count) 224 public void EnqueueToSTPNextNWorkItem(int count)
225 { 225 {
226 for (int i = 0; i < count; ++i) 226 for (int i = 0; i < count; ++i)
227 { 227 {
@@ -229,115 +229,115 @@ namespace Amib.Threading.Internal
229 } 229 }
230 } 230 }
231 231
232 private object FireOnIdle(object state) 232 private object FireOnIdle(object state)
233 { 233 {
234 FireOnIdleImpl(_onIdle); 234 FireOnIdleImpl(_onIdle);
235 return null; 235 return null;
236 } 236 }
237 237
238 [MethodImpl(MethodImplOptions.NoInlining)] 238 [MethodImpl(MethodImplOptions.NoInlining)]
239 private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle) 239 private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
240 { 240 {
241 if(null == onIdle) 241 if(null == onIdle)
242 { 242 {
243 return; 243 return;
244 } 244 }
245 245
246 Delegate[] delegates = onIdle.GetInvocationList(); 246 Delegate[] delegates = onIdle.GetInvocationList();
247 foreach(WorkItemsGroupIdleHandler eh in delegates) 247 foreach(WorkItemsGroupIdleHandler eh in delegates)
248 { 248 {
249 try 249 try
250 { 250 {
251 eh(this); 251 eh(this);
252 } 252 }
253 catch { } // Suppress exceptions 253 catch { } // Suppress exceptions
254 } 254 }
255 } 255 }
256 256
257 private void OnWorkItemStartedCallback(WorkItem workItem) 257 private void OnWorkItemStartedCallback(WorkItem workItem)
258 { 258 {
259 lock(_lock) 259 lock(_lock)
260 { 260 {
261 ++_workItemsExecutingInStp; 261 ++_workItemsExecutingInStp;
262 } 262 }
263 } 263 }
264 264
265 private void OnWorkItemCompletedCallback(WorkItem workItem) 265 private void OnWorkItemCompletedCallback(WorkItem workItem)
266 { 266 {
267 EnqueueToSTPNextWorkItem(null, true); 267 EnqueueToSTPNextWorkItem(null, true);
268 } 268 }
269 269
270 internal override void Enqueue(WorkItem workItem) 270 internal override void Enqueue(WorkItem workItem)
271 { 271 {
272 EnqueueToSTPNextWorkItem(workItem); 272 EnqueueToSTPNextWorkItem(workItem);
273 } 273 }
274 274
275 private void EnqueueToSTPNextWorkItem(WorkItem workItem) 275 private void EnqueueToSTPNextWorkItem(WorkItem workItem)
276 { 276 {
277 EnqueueToSTPNextWorkItem(workItem, false); 277 EnqueueToSTPNextWorkItem(workItem, false);
278 } 278 }
279 279
280 private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue) 280 private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
281 { 281 {
282 lock(_lock) 282 lock(_lock)
283 { 283 {
284 // Got here from OnWorkItemCompletedCallback() 284 // Got here from OnWorkItemCompletedCallback()
285 if (decrementWorkItemsInStpQueue) 285 if (decrementWorkItemsInStpQueue)
286 { 286 {
287 --_workItemsInStpQueue; 287 --_workItemsInStpQueue;
288 288
289 if(_workItemsInStpQueue < 0) 289 if(_workItemsInStpQueue < 0)
290 { 290 {
291 _workItemsInStpQueue = 0; 291 _workItemsInStpQueue = 0;
292 } 292 }
293 293
294 --_workItemsExecutingInStp; 294 --_workItemsExecutingInStp;
295 295
296 if(_workItemsExecutingInStp < 0) 296 if(_workItemsExecutingInStp < 0)
297 { 297 {
298 _workItemsExecutingInStp = 0; 298 _workItemsExecutingInStp = 0;
299 } 299 }
300 } 300 }
301 301
302 // If the work item is not null then enqueue it 302 // If the work item is not null then enqueue it
303 if (null != workItem) 303 if (null != workItem)
304 { 304 {
305 workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup; 305 workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
306 306
307 RegisterToWorkItemCompletion(workItem.GetWorkItemResult()); 307 RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
308 _workItemsQueue.Enqueue(workItem); 308 _workItemsQueue.Enqueue(workItem);
309 //_stp.IncrementWorkItemsCount(); 309 //_stp.IncrementWorkItemsCount();
310 310
311 if ((1 == _workItemsQueue.Count) && 311 if ((1 == _workItemsQueue.Count) &&
312 (0 == _workItemsInStpQueue)) 312 (0 == _workItemsInStpQueue))
313 { 313 {
314 _stp.RegisterWorkItemsGroup(this); 314 _stp.RegisterWorkItemsGroup(this);
315 IsIdle = false; 315 IsIdle = false;
316 _isIdleWaitHandle.Reset(); 316 _isIdleWaitHandle.Reset();
317 } 317 }
318 } 318 }
319 319
320 // If the work items queue of the group is empty than quit 320 // If the work items queue of the group is empty than quit
321 if (0 == _workItemsQueue.Count) 321 if (0 == _workItemsQueue.Count)
322 { 322 {
323 if (0 == _workItemsInStpQueue) 323 if (0 == _workItemsInStpQueue)
324 { 324 {
325 _stp.UnregisterWorkItemsGroup(this); 325 _stp.UnregisterWorkItemsGroup(this);
326 IsIdle = true; 326 IsIdle = true;
327 _isIdleWaitHandle.Set(); 327 _isIdleWaitHandle.Set();
328 if (decrementWorkItemsInStpQueue && _onIdle != null && _onIdle.GetInvocationList().Length > 0) 328 if (decrementWorkItemsInStpQueue && _onIdle != null && _onIdle.GetInvocationList().Length > 0)
329 { 329 {
330 _stp.QueueWorkItem(new WorkItemCallback(FireOnIdle)); 330 _stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
331 } 331 }
332 } 332 }
333 return; 333 return;
334 } 334 }
335 335
336 if (!_isSuspended) 336 if (!_isSuspended)
337 { 337 {
338 if (_workItemsInStpQueue < _concurrency) 338 if (_workItemsInStpQueue < _concurrency)
339 { 339 {
340 WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem; 340 WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
341 try 341 try
342 { 342 {
343 _stp.Enqueue(nextWorkItem); 343 _stp.Enqueue(nextWorkItem);
@@ -348,14 +348,14 @@ namespace Amib.Threading.Internal
348 // The STP has been shutdown 348 // The STP has been shutdown
349 } 349 }
350 350
351 ++_workItemsInStpQueue; 351 ++_workItemsInStpQueue;
352 } 352 }
353 } 353 }
354 } 354 }
355 } 355 }
356 356
357 #endregion 357 #endregion
358 } 358 }
359 359
360 #endregion 360 #endregion
361} 361}
diff --git a/ThirdParty/SmartThreadPool/WorkItemsGroupBase.cs b/ThirdParty/SmartThreadPool/WorkItemsGroupBase.cs
index 27fae5e..3a5dcc6 100644
--- a/ThirdParty/SmartThreadPool/WorkItemsGroupBase.cs
+++ b/ThirdParty/SmartThreadPool/WorkItemsGroupBase.cs
@@ -132,7 +132,7 @@ namespace Amib.Threading.Internal
132 /// </summary> 132 /// </summary>
133 /// <param name="callback">A callback to execute</param> 133 /// <param name="callback">A callback to execute</param>
134 /// <param name="state"> 134 /// <param name="state">
135 /// The context object of the work item. Used for passing arguments to the work item. 135 /// The context object of the work item. Used for passing arguments to the work item.
136 /// </param> 136 /// </param>
137 /// <returns>Returns a work item result</returns> 137 /// <returns>Returns a work item result</returns>
138 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state) 138 public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
@@ -147,7 +147,7 @@ namespace Amib.Threading.Internal
147 /// </summary> 147 /// </summary>
148 /// <param name="callback">A callback to execute</param> 148 /// <param name="callback">A callback to execute</param>
149 /// <param name="state"> 149 /// <param name="state">
150 /// The context object of the work item. Used for passing arguments to the work item. 150 /// The context object of the work item. Used for passing arguments to the work item.
151 /// </param> 151 /// </param>
152 /// <param name="workItemPriority">The work item priority</param> 152 /// <param name="workItemPriority">The work item priority</param>
153 /// <returns>Returns a work item result</returns> 153 /// <returns>Returns a work item result</returns>
@@ -165,7 +165,7 @@ namespace Amib.Threading.Internal
165 /// <param name="workItemInfo">Work item information</param> 165 /// <param name="workItemInfo">Work item information</param>
166 /// <param name="callback">A callback to execute</param> 166 /// <param name="callback">A callback to execute</param>
167 /// <param name="state"> 167 /// <param name="state">
168 /// The context object of the work item. Used for passing arguments to the work item. 168 /// The context object of the work item. Used for passing arguments to the work item.
169 /// </param> 169 /// </param>
170 /// <returns>Returns a work item result</returns> 170 /// <returns>Returns a work item result</returns>
171 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state) 171 public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
@@ -181,7 +181,7 @@ namespace Amib.Threading.Internal
181 /// </summary> 181 /// </summary>
182 /// <param name="callback">A callback to execute</param> 182 /// <param name="callback">A callback to execute</param>
183 /// <param name="state"> 183 /// <param name="state">
184 /// The context object of the work item. Used for passing arguments to the work item. 184 /// The context object of the work item. Used for passing arguments to the work item.
185 /// </param> 185 /// </param>
186 /// <param name="postExecuteWorkItemCallback"> 186 /// <param name="postExecuteWorkItemCallback">
187 /// A delegate to call after the callback completion 187 /// A delegate to call after the callback completion
@@ -203,7 +203,7 @@ namespace Amib.Threading.Internal
203 /// </summary> 203 /// </summary>
204 /// <param name="callback">A callback to execute</param> 204 /// <param name="callback">A callback to execute</param>
205 /// <param name="state"> 205 /// <param name="state">
206 /// The context object of the work item. Used for passing arguments to the work item. 206 /// The context object of the work item. Used for passing arguments to the work item.
207 /// </param> 207 /// </param>
208 /// <param name="postExecuteWorkItemCallback"> 208 /// <param name="postExecuteWorkItemCallback">
209 /// A delegate to call after the callback completion 209 /// A delegate to call after the callback completion
@@ -227,7 +227,7 @@ namespace Amib.Threading.Internal
227 /// </summary> 227 /// </summary>
228 /// <param name="callback">A callback to execute</param> 228 /// <param name="callback">A callback to execute</param>
229 /// <param name="state"> 229 /// <param name="state">
230 /// The context object of the work item. Used for passing arguments to the work item. 230 /// The context object of the work item. Used for passing arguments to the work item.
231 /// </param> 231 /// </param>
232 /// <param name="postExecuteWorkItemCallback"> 232 /// <param name="postExecuteWorkItemCallback">
233 /// A delegate to call after the callback completion 233 /// A delegate to call after the callback completion
@@ -251,7 +251,7 @@ namespace Amib.Threading.Internal
251 /// </summary> 251 /// </summary>
252 /// <param name="callback">A callback to execute</param> 252 /// <param name="callback">A callback to execute</param>
253 /// <param name="state"> 253 /// <param name="state">
254 /// The context object of the work item. Used for passing arguments to the work item. 254 /// The context object of the work item. Used for passing arguments to the work item.
255 /// </param> 255 /// </param>
256 /// <param name="postExecuteWorkItemCallback"> 256 /// <param name="postExecuteWorkItemCallback">
257 /// A delegate to call after the callback completion 257 /// A delegate to call after the callback completion
diff --git a/ThirdParty/SmartThreadPool/WorkItemsQueue.cs b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs
index e0bc916..21403a0 100644
--- a/ThirdParty/SmartThreadPool/WorkItemsQueue.cs
+++ b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs
@@ -4,29 +4,29 @@ using System.Threading;
4 4
5namespace Amib.Threading.Internal 5namespace Amib.Threading.Internal
6{ 6{
7 #region WorkItemsQueue class 7 #region WorkItemsQueue class
8 8
9 /// <summary> 9 /// <summary>
10 /// WorkItemsQueue class. 10 /// WorkItemsQueue class.
11 /// </summary> 11 /// </summary>
12 public class WorkItemsQueue : IDisposable 12 public class WorkItemsQueue : IDisposable
13 { 13 {
14 #region Member variables 14 #region Member variables
15 15
16 /// <summary> 16 /// <summary>
17 /// Waiters queue (implemented as stack). 17 /// Waiters queue (implemented as stack).
18 /// </summary> 18 /// </summary>
19 private readonly WaiterEntry _headWaiterEntry = new WaiterEntry(); 19 private readonly WaiterEntry _headWaiterEntry = new WaiterEntry();
20 20
21 /// <summary> 21 /// <summary>
22 /// Waiters count 22 /// Waiters count
23 /// </summary> 23 /// </summary>
24 private int _waitersCount = 0; 24 private int _waitersCount = 0;
25 25
26 /// <summary> 26 /// <summary>
27 /// Work items queue 27 /// Work items queue
28 /// </summary> 28 /// </summary>
29 private readonly PriorityQueue _workItems = new PriorityQueue(); 29 private readonly PriorityQueue _workItems = new PriorityQueue();
30 30
31 /// <summary> 31 /// <summary>
32 /// Indicate that work items are allowed to be queued 32 /// Indicate that work items are allowed to be queued
@@ -34,7 +34,7 @@ namespace Amib.Threading.Internal
34 private bool _isWorkItemsQueueActive = true; 34 private bool _isWorkItemsQueueActive = true;
35 35
36 36
37#if (WINDOWS_PHONE) 37#if (WINDOWS_PHONE)
38 private static readonly Dictionary<int, WaiterEntry> _waiterEntries = new Dictionary<int, WaiterEntry>(); 38 private static readonly Dictionary<int, WaiterEntry> _waiterEntries = new Dictionary<int, WaiterEntry>();
39#elif (_WINDOWS_CE) 39#elif (_WINDOWS_CE)
40 private static LocalDataStoreSlot _waiterEntrySlot = Thread.AllocateDataSlot(); 40 private static LocalDataStoreSlot _waiterEntrySlot = Thread.AllocateDataSlot();
@@ -50,7 +50,7 @@ namespace Amib.Threading.Internal
50 /// </summary> 50 /// </summary>
51 private static WaiterEntry CurrentWaiterEntry 51 private static WaiterEntry CurrentWaiterEntry
52 { 52 {
53#if (WINDOWS_PHONE) 53#if (WINDOWS_PHONE)
54 get 54 get
55 { 55 {
56 lock (_waiterEntries) 56 lock (_waiterEntries)
@@ -92,60 +92,60 @@ namespace Amib.Threading.Internal
92 } 92 }
93 93
94 /// <summary> 94 /// <summary>
95 /// A flag that indicates if the WorkItemsQueue has been disposed. 95 /// A flag that indicates if the WorkItemsQueue has been disposed.
96 /// </summary> 96 /// </summary>
97 private bool _isDisposed = false; 97 private bool _isDisposed = false;
98 98
99 #endregion 99 #endregion
100 100
101 #region Public properties 101 #region Public properties
102 102
103 /// <summary> 103 /// <summary>
104 /// Returns the current number of work items in the queue 104 /// Returns the current number of work items in the queue
105 /// </summary> 105 /// </summary>
106 public int Count 106 public int Count
107 { 107 {
108 get 108 get
109 { 109 {
110 return _workItems.Count; 110 return _workItems.Count;
111 } 111 }
112 } 112 }
113 113
114 /// <summary> 114 /// <summary>
115 /// Returns the current number of waiters 115 /// Returns the current number of waiters
116 /// </summary> 116 /// </summary>
117 public int WaitersCount 117 public int WaitersCount
118 { 118 {
119 get 119 get
120 { 120 {
121 return _waitersCount; 121 return _waitersCount;
122 } 122 }
123 } 123 }
124 124
125 125
126 #endregion 126 #endregion
127 127
128 #region Public methods 128 #region Public methods
129 129
130 /// <summary> 130 /// <summary>
131 /// Enqueue a work item to the queue. 131 /// Enqueue a work item to the queue.
132 /// </summary> 132 /// </summary>
133 public bool EnqueueWorkItem(WorkItem workItem) 133 public bool EnqueueWorkItem(WorkItem workItem)
134 { 134 {
135 // A work item cannot be null, since null is used in the 135 // A work item cannot be null, since null is used in the
136 // WaitForWorkItem() method to indicate timeout or cancel 136 // WaitForWorkItem() method to indicate timeout or cancel
137 if (null == workItem) 137 if (null == workItem)
138 { 138 {
139 throw new ArgumentNullException("workItem" , "workItem cannot be null"); 139 throw new ArgumentNullException("workItem" , "workItem cannot be null");
140 } 140 }
141 141
142 bool enqueue = true; 142 bool enqueue = true;
143 143
144 // First check if there is a waiter waiting for work item. During 144 // First check if there is a waiter waiting for work item. During
145 // the check, timed out waiters are ignored. If there is no 145 // the check, timed out waiters are ignored. If there is no
146 // waiter then the work item is queued. 146 // waiter then the work item is queued.
147 lock(this) 147 lock(this)
148 { 148 {
149 ValidateNotDisposed(); 149 ValidateNotDisposed();
150 150
151 if (!_isWorkItemsQueueActive) 151 if (!_isWorkItemsQueueActive)
@@ -153,55 +153,55 @@ namespace Amib.Threading.Internal
153 return false; 153 return false;
154 } 154 }
155 155
156 while(_waitersCount > 0) 156 while(_waitersCount > 0)
157 { 157 {
158 // Dequeue a waiter. 158 // Dequeue a waiter.
159 WaiterEntry waiterEntry = PopWaiter(); 159 WaiterEntry waiterEntry = PopWaiter();
160 160
161 // Signal the waiter. On success break the loop 161 // Signal the waiter. On success break the loop
162 if (waiterEntry.Signal(workItem)) 162 if (waiterEntry.Signal(workItem))
163 { 163 {
164 enqueue = false; 164 enqueue = false;
165 break; 165 break;
166 } 166 }
167 } 167 }
168 168
169 if (enqueue) 169 if (enqueue)
170 { 170 {
171 // Enqueue the work item 171 // Enqueue the work item
172 _workItems.Enqueue(workItem); 172 _workItems.Enqueue(workItem);
173 } 173 }
174 } 174 }
175 return true; 175 return true;
176 } 176 }
177 177
178 178
179 /// <summary> 179 /// <summary>
180 /// Waits for a work item or exits on timeout or cancel 180 /// Waits for a work item or exits on timeout or cancel
181 /// </summary> 181 /// </summary>
182 /// <param name="millisecondsTimeout">Timeout in milliseconds</param> 182 /// <param name="millisecondsTimeout">Timeout in milliseconds</param>
183 /// <param name="cancelEvent">Cancel wait handle</param> 183 /// <param name="cancelEvent">Cancel wait handle</param>
184 /// <returns>Returns true if the resource was granted</returns> 184 /// <returns>Returns true if the resource was granted</returns>
185 public WorkItem DequeueWorkItem( 185 public WorkItem DequeueWorkItem(
186 int millisecondsTimeout, 186 int millisecondsTimeout,
187 WaitHandle cancelEvent) 187 WaitHandle cancelEvent)
188 { 188 {
189 // This method cause the caller to wait for a work item. 189 // This method cause the caller to wait for a work item.
190 // If there is at least one waiting work item then the 190 // If there is at least one waiting work item then the
191 // method returns immidiately with it. 191 // method returns immidiately with it.
192 // 192 //
193 // If there are no waiting work items then the caller 193 // If there are no waiting work items then the caller
194 // is queued between other waiters for a work item to arrive. 194 // is queued between other waiters for a work item to arrive.
195 // 195 //
196 // If a work item didn't come within millisecondsTimeout or 196 // If a work item didn't come within millisecondsTimeout or
197 // the user canceled the wait by signaling the cancelEvent 197 // the user canceled the wait by signaling the cancelEvent
198 // then the method returns null to indicate that the caller 198 // then the method returns null to indicate that the caller
199 // didn't get a work item. 199 // didn't get a work item.
200 200
201 WaiterEntry waiterEntry; 201 WaiterEntry waiterEntry;
202 WorkItem workItem = null; 202 WorkItem workItem = null;
203 lock (this) 203 lock (this)
204 { 204 {
205 ValidateNotDisposed(); 205 ValidateNotDisposed();
206 206
207 // If there are waiting work items then take one and return. 207 // If there are waiting work items then take one and return.
@@ -218,68 +218,68 @@ namespace Amib.Threading.Internal
218 218
219 // Put the waiter with the other waiters 219 // Put the waiter with the other waiters
220 PushWaiter(waiterEntry); 220 PushWaiter(waiterEntry);
221 } 221 }
222 222
223 // Prepare array of wait handle for the WaitHandle.WaitAny() 223 // Prepare array of wait handle for the WaitHandle.WaitAny()
224 WaitHandle [] waitHandles = new WaitHandle[] { 224 WaitHandle [] waitHandles = new WaitHandle[] {
225 waiterEntry.WaitHandle, 225 waiterEntry.WaitHandle,
226 cancelEvent }; 226 cancelEvent };
227 227
228 // Wait for an available resource, cancel event, or timeout. 228 // Wait for an available resource, cancel event, or timeout.
229 229
230 // During the wait we are supposes to exit the synchronization 230 // During the wait we are supposes to exit the synchronization
231 // domain. (Placing true as the third argument of the WaitAny()) 231 // domain. (Placing true as the third argument of the WaitAny())
232 // It just doesn't work, I don't know why, so I have two lock(this) 232 // It just doesn't work, I don't know why, so I have two lock(this)
233 // statments instead of one. 233 // statments instead of one.
234 234
235 int index = STPEventWaitHandle.WaitAny( 235 int index = STPEventWaitHandle.WaitAny(
236 waitHandles, 236 waitHandles,
237 millisecondsTimeout, 237 millisecondsTimeout,
238 true); 238 true);
239 239
240 lock(this) 240 lock(this)
241 { 241 {
242 // success is true if it got a work item. 242 // success is true if it got a work item.
243 bool success = (0 == index); 243 bool success = (0 == index);
244 244
245 // The timeout variable is used only for readability. 245 // The timeout variable is used only for readability.
246 // (We treat cancel as timeout) 246 // (We treat cancel as timeout)
247 bool timeout = !success; 247 bool timeout = !success;
248 248
249 // On timeout update the waiterEntry that it is timed out 249 // On timeout update the waiterEntry that it is timed out
250 if (timeout) 250 if (timeout)
251 { 251 {
252 // The Timeout() fails if the waiter has already been signaled 252 // The Timeout() fails if the waiter has already been signaled
253 timeout = waiterEntry.Timeout(); 253 timeout = waiterEntry.Timeout();
254 254
255 // On timeout remove the waiter from the queue. 255 // On timeout remove the waiter from the queue.
256 // Note that the complexity is O(1). 256 // Note that the complexity is O(1).
257 if(timeout) 257 if(timeout)
258 { 258 {
259 RemoveWaiter(waiterEntry, false); 259 RemoveWaiter(waiterEntry, false);
260 } 260 }
261 261
262 // Again readability 262 // Again readability
263 success = !timeout; 263 success = !timeout;
264 } 264 }
265 265
266 // On success return the work item 266 // On success return the work item
267 if (success) 267 if (success)
268 { 268 {
269 workItem = waiterEntry.WorkItem; 269 workItem = waiterEntry.WorkItem;
270 270
271 if (null == workItem) 271 if (null == workItem)
272 { 272 {
273 workItem = _workItems.Dequeue() as WorkItem; 273 workItem = _workItems.Dequeue() as WorkItem;
274 } 274 }
275 } 275 }
276 } 276 }
277 // On failure return null. 277 // On failure return null.
278 return workItem; 278 return workItem;
279 } 279 }
280 280
281 /// <summary> 281 /// <summary>
282 /// Cleanup the work items queue, hence no more work 282 /// Cleanup the work items queue, hence no more work
283 /// items are allowed to be queue 283 /// items are allowed to be queue
284 /// </summary> 284 /// </summary>
285 private void Cleanup() 285 private void Cleanup()
@@ -303,19 +303,19 @@ namespace Amib.Threading.Internal
303 // Clear the work items that are already queued 303 // Clear the work items that are already queued
304 _workItems.Clear(); 304 _workItems.Clear();
305 305
306 // Note: 306 // Note:
307 // I don't iterate over the queue and dispose of work items's states, 307 // I don't iterate over the queue and dispose of work items's states,
308 // since if a work item has a state object that is still in use in the 308 // since if a work item has a state object that is still in use in the
309 // application then I must not dispose it. 309 // application then I must not dispose it.
310 310
311 // Tell the waiters that they were timed out. 311 // Tell the waiters that they were timed out.
312 // It won't signal them to exit, but to ignore their 312 // It won't signal them to exit, but to ignore their
313 // next work item. 313 // next work item.
314 while(_waitersCount > 0) 314 while(_waitersCount > 0)
315 { 315 {
316 WaiterEntry waiterEntry = PopWaiter(); 316 WaiterEntry waiterEntry = PopWaiter();
317 waiterEntry.Timeout(); 317 waiterEntry.Timeout();
318 } 318 }
319 } 319 }
320 } 320 }
321 321
@@ -334,275 +334,275 @@ namespace Amib.Threading.Internal
334 } 334 }
335 } 335 }
336 336
337 #endregion 337 #endregion
338 338
339 #region Private methods 339 #region Private methods
340 340
341 /// <summary> 341 /// <summary>
342 /// Returns the WaiterEntry of the current thread 342 /// Returns the WaiterEntry of the current thread
343 /// </summary> 343 /// </summary>
344 /// <returns></returns> 344 /// <returns></returns>
345 /// In order to avoid creation and destuction of WaiterEntry 345 /// In order to avoid creation and destuction of WaiterEntry
346 /// objects each thread has its own WaiterEntry object. 346 /// objects each thread has its own WaiterEntry object.
347 private static WaiterEntry GetThreadWaiterEntry() 347 private static WaiterEntry GetThreadWaiterEntry()
348 { 348 {
349 if (null == CurrentWaiterEntry) 349 if (null == CurrentWaiterEntry)
350 { 350 {
351 CurrentWaiterEntry = new WaiterEntry(); 351 CurrentWaiterEntry = new WaiterEntry();
352 } 352 }
353 CurrentWaiterEntry.Reset(); 353 CurrentWaiterEntry.Reset();
354 return CurrentWaiterEntry; 354 return CurrentWaiterEntry;
355 } 355 }
356 356
357 #region Waiters stack methods 357 #region Waiters stack methods
358 358
359 /// <summary> 359 /// <summary>
360 /// Push a new waiter into the waiter's stack 360 /// Push a new waiter into the waiter's stack
361 /// </summary> 361 /// </summary>
362 /// <param name="newWaiterEntry">A waiter to put in the stack</param> 362 /// <param name="newWaiterEntry">A waiter to put in the stack</param>
363 public void PushWaiter(WaiterEntry newWaiterEntry) 363 public void PushWaiter(WaiterEntry newWaiterEntry)
364 { 364 {
365 // Remove the waiter if it is already in the stack and 365 // Remove the waiter if it is already in the stack and
366 // update waiter's count as needed 366 // update waiter's count as needed
367 RemoveWaiter(newWaiterEntry, false); 367 RemoveWaiter(newWaiterEntry, false);
368 368
369 // If the stack is empty then newWaiterEntry is the new head of the stack 369 // If the stack is empty then newWaiterEntry is the new head of the stack
370 if (null == _headWaiterEntry._nextWaiterEntry) 370 if (null == _headWaiterEntry._nextWaiterEntry)
371 { 371 {
372 _headWaiterEntry._nextWaiterEntry = newWaiterEntry; 372 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
373 newWaiterEntry._prevWaiterEntry = _headWaiterEntry; 373 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
374 374
375 } 375 }
376 // If the stack is not empty then put newWaiterEntry as the new head 376 // If the stack is not empty then put newWaiterEntry as the new head
377 // of the stack. 377 // of the stack.
378 else 378 else
379 { 379 {
380 // Save the old first waiter entry 380 // Save the old first waiter entry
381 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry; 381 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
382 382
383 // Update the links 383 // Update the links
384 _headWaiterEntry._nextWaiterEntry = newWaiterEntry; 384 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
385 newWaiterEntry._nextWaiterEntry = oldFirstWaiterEntry; 385 newWaiterEntry._nextWaiterEntry = oldFirstWaiterEntry;
386 newWaiterEntry._prevWaiterEntry = _headWaiterEntry; 386 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
387 oldFirstWaiterEntry._prevWaiterEntry = newWaiterEntry; 387 oldFirstWaiterEntry._prevWaiterEntry = newWaiterEntry;
388 } 388 }
389 389
390 // Increment the number of waiters 390 // Increment the number of waiters
391 ++_waitersCount; 391 ++_waitersCount;
392 } 392 }
393 393
394 /// <summary> 394 /// <summary>
395 /// Pop a waiter from the waiter's stack 395 /// Pop a waiter from the waiter's stack
396 /// </summary> 396 /// </summary>
397 /// <returns>Returns the first waiter in the stack</returns> 397 /// <returns>Returns the first waiter in the stack</returns>
398 private WaiterEntry PopWaiter() 398 private WaiterEntry PopWaiter()
399 { 399 {
400 // Store the current stack head 400 // Store the current stack head
401 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry; 401 WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
402 402
403 // Store the new stack head 403 // Store the new stack head
404 WaiterEntry newHeadWaiterEntry = oldFirstWaiterEntry._nextWaiterEntry; 404 WaiterEntry newHeadWaiterEntry = oldFirstWaiterEntry._nextWaiterEntry;
405 405
406 // Update the old stack head list links and decrement the number 406 // Update the old stack head list links and decrement the number
407 // waiters. 407 // waiters.
408 RemoveWaiter(oldFirstWaiterEntry, true); 408 RemoveWaiter(oldFirstWaiterEntry, true);
409 409
410 // Update the new stack head 410 // Update the new stack head
411 _headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry; 411 _headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
412 if (null != newHeadWaiterEntry) 412 if (null != newHeadWaiterEntry)
413 { 413 {
414 newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry; 414 newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
415 } 415 }
416 416
417 // Return the old stack head 417 // Return the old stack head
418 return oldFirstWaiterEntry; 418 return oldFirstWaiterEntry;
419 } 419 }
420 420
421 /// <summary> 421 /// <summary>
422 /// Remove a waiter from the stack 422 /// Remove a waiter from the stack
423 /// </summary> 423 /// </summary>
424 /// <param name="waiterEntry">A waiter entry to remove</param> 424 /// <param name="waiterEntry">A waiter entry to remove</param>
425 /// <param name="popDecrement">If true the waiter count is always decremented</param> 425 /// <param name="popDecrement">If true the waiter count is always decremented</param>
426 private void RemoveWaiter(WaiterEntry waiterEntry, bool popDecrement) 426 private void RemoveWaiter(WaiterEntry waiterEntry, bool popDecrement)
427 { 427 {
428 // Store the prev entry in the list 428 // Store the prev entry in the list
429 WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry; 429 WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry;
430 430
431 // Store the next entry in the list 431 // Store the next entry in the list
432 WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry; 432 WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry;
433 433
434 // A flag to indicate if we need to decrement the waiters count. 434 // A flag to indicate if we need to decrement the waiters count.
435 // If we got here from PopWaiter then we must decrement. 435 // If we got here from PopWaiter then we must decrement.
436 // If we got here from PushWaiter then we decrement only if 436 // If we got here from PushWaiter then we decrement only if
437 // the waiter was already in the stack. 437 // the waiter was already in the stack.
438 bool decrementCounter = popDecrement; 438 bool decrementCounter = popDecrement;
439 439
440 // Null the waiter's entry links 440 // Null the waiter's entry links
441 waiterEntry._prevWaiterEntry = null; 441 waiterEntry._prevWaiterEntry = null;
442 waiterEntry._nextWaiterEntry = null; 442 waiterEntry._nextWaiterEntry = null;
443 443
444 // If the waiter entry had a prev link then update it. 444 // If the waiter entry had a prev link then update it.
445 // It also means that the waiter is already in the list and we 445 // It also means that the waiter is already in the list and we
446 // need to decrement the waiters count. 446 // need to decrement the waiters count.
447 if (null != prevWaiterEntry) 447 if (null != prevWaiterEntry)
448 { 448 {
449 prevWaiterEntry._nextWaiterEntry = nextWaiterEntry; 449 prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
450 decrementCounter = true; 450 decrementCounter = true;
451 } 451 }
452 452
453 // If the waiter entry had a next link then update it. 453 // If the waiter entry had a next link then update it.
454 // It also means that the waiter is already in the list and we 454 // It also means that the waiter is already in the list and we
455 // need to decrement the waiters count. 455 // need to decrement the waiters count.
456 if (null != nextWaiterEntry) 456 if (null != nextWaiterEntry)
457 { 457 {
458 nextWaiterEntry._prevWaiterEntry = prevWaiterEntry; 458 nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
459 decrementCounter = true; 459 decrementCounter = true;
460 } 460 }
461 461
462 // Decrement the waiters count if needed 462 // Decrement the waiters count if needed
463 if (decrementCounter) 463 if (decrementCounter)
464 { 464 {
465 --_waitersCount; 465 --_waitersCount;
466 } 466 }
467 } 467 }
468 468
469 #endregion 469 #endregion
470 470
471 #endregion 471 #endregion
472 472
473 #region WaiterEntry class 473 #region WaiterEntry class
474 474
475 // A waiter entry in the _waiters queue. 475 // A waiter entry in the _waiters queue.
476 public sealed class WaiterEntry : IDisposable 476 public sealed class WaiterEntry : IDisposable
477 { 477 {
478 #region Member variables 478 #region Member variables
479 479
480 /// <summary> 480 /// <summary>
481 /// Event to signal the waiter that it got the work item. 481 /// Event to signal the waiter that it got the work item.
482 /// </summary> 482 /// </summary>
483 //private AutoResetEvent _waitHandle = new AutoResetEvent(false); 483 //private AutoResetEvent _waitHandle = new AutoResetEvent(false);
484 private AutoResetEvent _waitHandle = EventWaitHandleFactory.CreateAutoResetEvent(); 484 private AutoResetEvent _waitHandle = EventWaitHandleFactory.CreateAutoResetEvent();
485 485
486 /// <summary> 486 /// <summary>
487 /// Flag to know if this waiter already quited from the queue 487 /// Flag to know if this waiter already quited from the queue
488 /// because of a timeout. 488 /// because of a timeout.
489 /// </summary> 489 /// </summary>
490 private bool _isTimedout = false; 490 private bool _isTimedout = false;
491 491
492 /// <summary> 492 /// <summary>
493 /// Flag to know if the waiter was signaled and got a work item. 493 /// Flag to know if the waiter was signaled and got a work item.
494 /// </summary> 494 /// </summary>
495 private bool _isSignaled = false; 495 private bool _isSignaled = false;
496 496
497 /// <summary> 497 /// <summary>
498 /// A work item that passed directly to the waiter withou going 498 /// A work item that passed directly to the waiter withou going
499 /// through the queue 499 /// through the queue
500 /// </summary> 500 /// </summary>
501 private WorkItem _workItem = null; 501 private WorkItem _workItem = null;
502 502
503 private bool _isDisposed = false; 503 private bool _isDisposed = false;
504 504
505 // Linked list members 505 // Linked list members
506 internal WaiterEntry _nextWaiterEntry = null; 506 internal WaiterEntry _nextWaiterEntry = null;
507 internal WaiterEntry _prevWaiterEntry = null; 507 internal WaiterEntry _prevWaiterEntry = null;
508 508
509 #endregion 509 #endregion
510 510
511 #region Construction 511 #region Construction
512 512
513 public WaiterEntry() 513 public WaiterEntry()
514 { 514 {
515 Reset(); 515 Reset();
516 } 516 }
517 517
518 #endregion 518 #endregion
519 519
520 #region Public methods 520 #region Public methods
521 521
522 public WaitHandle WaitHandle 522 public WaitHandle WaitHandle
523 { 523 {
524 get { return _waitHandle; } 524 get { return _waitHandle; }
525 } 525 }
526 526
527 public WorkItem WorkItem 527 public WorkItem WorkItem
528 { 528 {
529 get 529 get
530 { 530 {
531 return _workItem; 531 return _workItem;
532 } 532 }
533 } 533 }
534 534
535 /// <summary> 535 /// <summary>
536 /// Signal the waiter that it got a work item. 536 /// Signal the waiter that it got a work item.
537 /// </summary> 537 /// </summary>
538 /// <returns>Return true on success</returns> 538 /// <returns>Return true on success</returns>
539 /// The method fails if Timeout() preceded its call 539 /// The method fails if Timeout() preceded its call
540 public bool Signal(WorkItem workItem) 540 public bool Signal(WorkItem workItem)
541 { 541 {
542 lock(this) 542 lock(this)
543 { 543 {
544 if (!_isTimedout) 544 if (!_isTimedout)
545 { 545 {
546 _workItem = workItem; 546 _workItem = workItem;
547 _isSignaled = true; 547 _isSignaled = true;
548 _waitHandle.Set(); 548 _waitHandle.Set();
549 return true; 549 return true;
550 } 550 }
551 } 551 }
552 return false; 552 return false;
553 } 553 }
554 554
555 /// <summary> 555 /// <summary>
556 /// Mark the wait entry that it has been timed out 556 /// Mark the wait entry that it has been timed out
557 /// </summary> 557 /// </summary>
558 /// <returns>Return true on success</returns> 558 /// <returns>Return true on success</returns>
559 /// The method fails if Signal() preceded its call 559 /// The method fails if Signal() preceded its call
560 public bool Timeout() 560 public bool Timeout()
561 { 561 {
562 lock(this) 562 lock(this)
563 { 563 {
564 // Time out can happen only if the waiter wasn't marked as 564 // Time out can happen only if the waiter wasn't marked as
565 // signaled 565 // signaled
566 if (!_isSignaled) 566 if (!_isSignaled)
567 { 567 {
568 // We don't remove the waiter from the queue, the DequeueWorkItem 568 // We don't remove the waiter from the queue, the DequeueWorkItem
569 // method skips _waiters that were timed out. 569 // method skips _waiters that were timed out.
570 _isTimedout = true; 570 _isTimedout = true;
571 return true; 571 return true;
572 } 572 }
573 } 573 }
574 return false; 574 return false;
575 } 575 }
576 576
577 /// <summary> 577 /// <summary>
578 /// Reset the wait entry so it can be used again 578 /// Reset the wait entry so it can be used again
579 /// </summary> 579 /// </summary>
580 public void Reset() 580 public void Reset()
581 { 581 {
582 _workItem = null; 582 _workItem = null;
583 _isTimedout = false; 583 _isTimedout = false;
584 _isSignaled = false; 584 _isSignaled = false;
585 _waitHandle.Reset(); 585 _waitHandle.Reset();
586 } 586 }
587 587
588 /// <summary> 588 /// <summary>
589 /// Free resources 589 /// Free resources
590 /// </summary> 590 /// </summary>
591 public void Close() 591 public void Close()
592 { 592 {
593 if (null != _waitHandle) 593 if (null != _waitHandle)
594 { 594 {
595 _waitHandle.Close(); 595 _waitHandle.Close();
596 _waitHandle = null; 596 _waitHandle = null;
597 } 597 }
598 } 598 }
599 599
600 #endregion 600 #endregion
601 601
602 #region IDisposable Members 602 #region IDisposable Members
603 603
604 public void Dispose() 604 public void Dispose()
605 { 605 {
606 lock (this) 606 lock (this)
607 { 607 {
608 if (!_isDisposed) 608 if (!_isDisposed)
@@ -613,10 +613,10 @@ namespace Amib.Threading.Internal
613 } 613 }
614 } 614 }
615 615
616 #endregion 616 #endregion
617 } 617 }
618 618
619 #endregion 619 #endregion
620 620
621 #region IDisposable Members 621 #region IDisposable Members
622 622
@@ -625,6 +625,7 @@ namespace Amib.Threading.Internal
625 if (!_isDisposed) 625 if (!_isDisposed)
626 { 626 {
627 Cleanup(); 627 Cleanup();
628 _headWaiterEntry.Close();
628 } 629 }
629 _isDisposed = true; 630 _isDisposed = true;
630 } 631 }
@@ -640,6 +641,6 @@ namespace Amib.Threading.Internal
640 #endregion 641 #endregion
641 } 642 }
642 643
643 #endregion 644 #endregion
644} 645}
645 646