diff --git a/ThirdParty/SmartThreadPool/STPEventWaitHandle.cs b/ThirdParty/SmartThreadPool/STPEventWaitHandle.cs index aca3a2c75c..9ddb3ccf6a 100644 --- a/ThirdParty/SmartThreadPool/STPEventWaitHandle.cs +++ b/ThirdParty/SmartThreadPool/STPEventWaitHandle.cs @@ -7,21 +7,25 @@ namespace Amib.Threading.Internal { public const int WaitTimeout = Timeout.Infinite; + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext); } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] internal static int WaitAny(WaitHandle[] waitHandles) { return WaitHandle.WaitAny(waitHandles); } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext); } + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext) { return waitHandle.WaitOne(millisecondsTimeout, exitContext); diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.cs index 74b54b5260..c2a0d6dd62 100644 --- a/ThirdParty/SmartThreadPool/SmartThreadPool.cs +++ b/ThirdParty/SmartThreadPool/SmartThreadPool.cs @@ -676,10 +676,6 @@ namespace Amib.Threading // Process until shutdown. while (!_shutdown) { - // Update the last time this thread was seen alive. - // It's good for debugging. - CurrentThreadEntry.IAmAlive(); - // The following block handles the when the MaxWorkerThreads has been // incremented by the user at run-time. // Double lock for quit. @@ -693,18 +689,17 @@ namespace Amib.Threading // This method must be called within this lock or else // more threads will quit and the thread pool will go // below the lower limit. - InformCompleted(); + //InformCompleted(); break; } } } + CurrentThreadEntry.IAmAlive(); + // Wait for a work item, shutdown, or timeout WorkItem workItem = Dequeue(); - // Update the last time this thread was seen alive. - // It's good for debugging. - CurrentThreadEntry.IAmAlive(); // On timeout or shut down. if (workItem == null) @@ -720,7 +715,7 @@ namespace Amib.Threading // This method must be called within this lock or else // more threads will quit and the thread pool will go // below the lower limit. - InformCompleted(); + //InformCompleted(); break; } } @@ -728,6 +723,8 @@ namespace Amib.Threading continue; } + CurrentThreadEntry.IAmAlive(); + try { // Initialize the value to false @@ -819,6 +816,7 @@ namespace Amib.Threading { InformCompleted(); FireOnThreadTermination(); + _workItemsQueue.CloseThreadWaiter(); } } diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs index 9806000159..96afae23f8 100644 --- a/ThirdParty/SmartThreadPool/WorkItem.cs +++ b/ThirdParty/SmartThreadPool/WorkItem.cs @@ -987,6 +987,12 @@ namespace Amib.Threading.Internal _callerContext = null; } + if(_workItemCompleted != null) + { + _workItemCompleted.Dispose(); + _workItemCompleted = null; + } + if (_workItemInfo.DisposeOfStateObjects) { IDisposable disp = _state as IDisposable; diff --git a/ThirdParty/SmartThreadPool/WorkItemsGroup.cs b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs index f5fba4b537..5321bb62a7 100644 --- a/ThirdParty/SmartThreadPool/WorkItemsGroup.cs +++ b/ThirdParty/SmartThreadPool/WorkItemsGroup.cs @@ -335,7 +335,7 @@ namespace Amib.Threading.Internal { if (_workItemsInStpQueue < _concurrency) { - WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem; + WorkItem nextWorkItem = _workItemsQueue.Dequeue(); try { _stp.Enqueue(nextWorkItem); diff --git a/ThirdParty/SmartThreadPool/WorkItemsQueue.cs b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs index 670a2e7a43..f7a031ae3c 100644 --- a/ThirdParty/SmartThreadPool/WorkItemsQueue.cs +++ b/ThirdParty/SmartThreadPool/WorkItemsQueue.cs @@ -36,22 +36,6 @@ namespace Amib.Threading.Internal [ThreadStatic] private static WaiterEntry _waiterEntry; - - /// - /// Each thread in the thread pool keeps its own waiter entry. - /// - private static WaiterEntry CurrentWaiterEntry - { - get - { - return _waiterEntry; - } - set - { - _waiterEntry = value; - } - } - /// /// A flag that indicates if the WorkItemsQueue has been disposed. /// @@ -95,13 +79,11 @@ namespace Amib.Threading.Internal { // A work item cannot be null, since null is used in the // WaitForWorkItem() method to indicate timeout or cancel - if (null == workItem) + if (workItem == null) { throw new ArgumentNullException("workItem", "workItem cannot be null"); } - bool enqueue = true; - // First check if there is a waiter waiting for work item. During // the check, timed out waiters are ignored. If there is no // waiter then the work item is queued. @@ -110,9 +92,7 @@ namespace Amib.Threading.Internal ValidateNotDisposed(); if (!_isWorkItemsQueueActive) - { return false; - } while (_waitersCount > 0) { @@ -121,21 +101,24 @@ namespace Amib.Threading.Internal // Signal the waiter. On success break the loop if (waiterEntry.Signal(workItem)) - { - enqueue = false; - break; - } + return true; } - if (enqueue) - { - // Enqueue the work item - _workItems.Enqueue(workItem); - } + // Enqueue the work item + _workItems.Enqueue(workItem); } return true; } + public void CloseThreadWaiter() + { + if(_waiterEntry != null) + { + _waiterEntry.Close(); + _waiterEntry = null; + } + } + /// /// Waits for a work item or exits on timeout or cancel @@ -158,17 +141,13 @@ namespace Amib.Threading.Internal // didn't get a work item. WaiterEntry waiterEntry; - WorkItem workItem = null; lock (this) { ValidateNotDisposed(); // If there are waiting work items then take one and return. if (_workItems.Count > 0) - { - workItem = _workItems.Dequeue(); - return workItem; - } + return _workItems.Dequeue(); // No waiting work items ... @@ -193,43 +172,26 @@ namespace Amib.Threading.Internal lock (this) { - // success is true if it got a work item. - bool success = (0 == index); - - // The timeout variable is used only for readability. - // (We treat cancel as timeout) - bool timeout = !success; - // On timeout update the waiterEntry that it is timed out - if (timeout) + if (index != 0) { // The Timeout() fails if the waiter has already been signaled - timeout = waiterEntry.Timeout(); - // On timeout remove the waiter from the queue. // Note that the complexity is O(1). - if (timeout) + if (waiterEntry.Timeout()) { RemoveWaiter(waiterEntry, false); + return null; } - - // Again readability - success = !timeout; } // On success return the work item - if (success) - { - workItem = waiterEntry.WorkItem; + WorkItem workItem = waiterEntry.WorkItem; + if (workItem == null) + workItem = _workItems.Dequeue(); - if (null == workItem) - { - workItem = _workItems.Dequeue(); - } - } + return workItem; } - // On failure return null. - return workItem; } /// @@ -300,12 +262,13 @@ namespace Amib.Threading.Internal /// objects each thread has its own WaiterEntry object. private static WaiterEntry GetThreadWaiterEntry() { - if (null == CurrentWaiterEntry) + if (_waiterEntry == null) { - CurrentWaiterEntry = new WaiterEntry(); + _waiterEntry = new WaiterEntry(); } - CurrentWaiterEntry.Reset(); - return CurrentWaiterEntry; + else + _waiterEntry.Reset(); + return _waiterEntry; } #region Waiters stack methods @@ -325,7 +288,6 @@ namespace Amib.Threading.Internal { _headWaiterEntry._nextWaiterEntry = newWaiterEntry; newWaiterEntry._prevWaiterEntry = _headWaiterEntry; - } // If the stack is not empty then put newWaiterEntry as the new head // of the stack. @@ -363,7 +325,7 @@ namespace Amib.Threading.Internal // Update the new stack head _headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry; - if (null != newHeadWaiterEntry) + if (newHeadWaiterEntry != null) { newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry; } @@ -381,43 +343,38 @@ namespace Amib.Threading.Internal { // Store the prev entry in the list WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry; + waiterEntry._prevWaiterEntry = null; // Store the next entry in the list WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry; + waiterEntry._nextWaiterEntry = null; - // A flag to indicate if we need to decrement the waiters count. + // popDecrement indicate if we need to decrement the waiters count. // If we got here from PopWaiter then we must decrement. // If we got here from PushWaiter then we decrement only if // the waiter was already in the stack. - bool decrementCounter = popDecrement; - - // Null the waiter's entry links - waiterEntry._prevWaiterEntry = null; - waiterEntry._nextWaiterEntry = null; // If the waiter entry had a prev link then update it. // It also means that the waiter is already in the list and we // need to decrement the waiters count. - if (null != prevWaiterEntry) + if (prevWaiterEntry != null) { prevWaiterEntry._nextWaiterEntry = nextWaiterEntry; - decrementCounter = true; + popDecrement = true; } // If the waiter entry had a next link then update it. // It also means that the waiter is already in the list and we // need to decrement the waiters count. - if (null != nextWaiterEntry) + if (nextWaiterEntry != null) { nextWaiterEntry._prevWaiterEntry = prevWaiterEntry; - decrementCounter = true; + popDecrement = true; } // Decrement the waiters count if needed - if (decrementCounter) - { + if (popDecrement) --_waitersCount; - } } #endregion @@ -434,7 +391,6 @@ namespace Amib.Threading.Internal /// /// Event to signal the waiter that it got the work item. /// - //private AutoResetEvent _waitHandle = new AutoResetEvent(false); private AutoResetEvent _waitHandle = new AutoResetEvent(false); /// @@ -466,7 +422,6 @@ namespace Amib.Threading.Internal public WaiterEntry() { - Reset(); } #endregion @@ -544,6 +499,7 @@ namespace Amib.Threading.Internal /// public void Close() { + _workItem = null; if (null != _waitHandle) { _waitHandle.Close(); @@ -562,8 +518,8 @@ namespace Amib.Threading.Internal if (!_isDisposed) { Close(); + _isDisposed = true; } - _isDisposed = true; } }