From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001
From: David Walter Seikel
Date: Thu, 3 Nov 2016 21:44:39 +1000
Subject: Initial update to OpenSim 0.8.2.1 source code.
---
ThirdParty/SmartThreadPool/WorkItem.cs | 659 ++++++++++++++++-----------------
1 file changed, 313 insertions(+), 346 deletions(-)
(limited to 'ThirdParty/SmartThreadPool/WorkItem.cs')
diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs
index d0c0524..185f10c 100644
--- a/ThirdParty/SmartThreadPool/WorkItem.cs
+++ b/ThirdParty/SmartThreadPool/WorkItem.cs
@@ -1,58 +1,13 @@
-// Ami Bar
-// amibar@gmail.com
-
using System;
using System.Threading;
using System.Diagnostics;
namespace Amib.Threading.Internal
{
- #region WorkItem Delegate
-
- ///
- /// An internal delegate to call when the WorkItem starts or completes
- ///
- internal delegate void WorkItemStateCallback(WorkItem workItem);
-
- #endregion
-
- #region IInternalWorkItemResult interface
-
- public class CanceledWorkItemsGroup
- {
- public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
-
- private bool _isCanceled = false;
- public bool IsCanceled
- {
- get { return _isCanceled; }
- set { _isCanceled = value; }
- }
- }
-
- internal interface IInternalWorkItemResult
- {
- event WorkItemStateCallback OnWorkItemStarted;
- event WorkItemStateCallback OnWorkItemCompleted;
- }
-
- #endregion
-
- #region IWorkItem interface
-
- public interface IWorkItem
- {
-
- }
-
- #endregion
-
- #region WorkItem class
-
///
/// Holds a callback delegate and the state for that delegate.
///
- public class WorkItem : IHasWorkItemPriority, IWorkItem
+ public partial class WorkItem : IHasWorkItemPriority
{
#region WorkItemState enum
@@ -61,33 +16,57 @@ namespace Amib.Threading.Internal
///
private enum WorkItemState
{
- InQueue,
- InProgress,
- Completed,
- Canceled,
+ InQueue = 0, // Nexts: InProgress, Canceled
+ InProgress = 1, // Nexts: Completed, Canceled
+ Completed = 2, // Stays Completed
+ Canceled = 3, // Stays Canceled
}
- #endregion
+ private static bool IsValidStatesTransition(WorkItemState currentState, WorkItemState nextState)
+ {
+ bool valid = false;
+
+ switch (currentState)
+ {
+ case WorkItemState.InQueue:
+ valid = (WorkItemState.InProgress == nextState) || (WorkItemState.Canceled == nextState);
+ break;
+ case WorkItemState.InProgress:
+ valid = (WorkItemState.Completed == nextState) || (WorkItemState.Canceled == nextState);
+ break;
+ case WorkItemState.Completed:
+ case WorkItemState.Canceled:
+ // Cannot be changed
+ break;
+ default:
+ // Unknown state
+ Debug.Assert(false);
+ break;
+ }
- #region Member Variables
+ return valid;
+ }
- public Thread currentThread;
+ #endregion
+
+ #region Fields
///
/// Callback delegate for the callback.
///
- private WorkItemCallback _callback;
+ private readonly WorkItemCallback _callback;
///
/// State with which to call the callback delegate.
///
private object _state;
+#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
///
/// Stores the caller's context
///
- private CallerThreadContext _callerContext;
-
+ private readonly CallerThreadContext _callerContext;
+#endif
///
/// Holds the result of the mehtod
///
@@ -117,12 +96,12 @@ namespace Amib.Threading.Internal
///
/// Represents the result state of the work item
///
- private WorkItemResult _workItemResult;
+ private readonly WorkItemResult _workItemResult;
///
/// Work item info
///
- private WorkItemInfo _workItemInfo;
+ private readonly WorkItemInfo _workItemInfo;
///
/// Called when the WorkItem starts
@@ -141,30 +120,41 @@ namespace Amib.Threading.Internal
private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
///
+ /// A reference to an object that indicates whatever the
+ /// SmartThreadPool has been canceled
+ ///
+ private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
+
+ ///
/// The work item group this work item belong to.
- ///
///
- private IWorkItemsGroup _workItemsGroup;
+ private readonly IWorkItemsGroup _workItemsGroup;
- #region Performance Counter fields
+ ///
+ /// The thread that executes this workitem.
+ /// This field is available for the period when the work item is executed, before and after it is null.
+ ///
+ private Thread _executingThread;
///
- /// The time when the work items is queued.
- /// Used with the performance counter.
+ /// The absulote time when the work item will be timeout
///
- private DateTime _queuedTime;
+ private long _expirationTime;
+
+ #region Performance Counter fields
+
+
+
///
- /// The time when the work items starts its execution.
- /// Used with the performance counter.
+ /// Stores how long the work item waited on the stp queue
///
- private DateTime _beginProcessTime;
+ private Stopwatch _waitingOnQueueStopwatch;
///
- /// The time when the work items ends its execution.
- /// Used with the performance counter.
+ /// Stores how much time it took the work item to execute after it went out of the queue
///
- private DateTime _endProcessTime;
+ private Stopwatch _processingStopwatch;
#endregion
@@ -174,17 +164,25 @@ namespace Amib.Threading.Internal
public TimeSpan WaitingTime
{
- get
+ get
{
- return (_beginProcessTime - _queuedTime);
+ return _waitingOnQueueStopwatch.Elapsed;
}
}
public TimeSpan ProcessTime
{
- get
+ get
+ {
+ return _processingStopwatch.Elapsed;
+ }
+ }
+
+ internal WorkItemInfo WorkItemInfo
+ {
+ get
{
- return (_endProcessTime - _beginProcessTime);
+ return _workItemInfo;
}
}
@@ -195,6 +193,8 @@ namespace Amib.Threading.Internal
///
/// Initialize the callback holding object.
///
+ /// The workItemGroup of the workitem
+ /// The WorkItemInfo of te workitem
/// Callback delegate for the callback.
/// State with which to call the callback delegate.
///
@@ -203,16 +203,18 @@ namespace Amib.Threading.Internal
public WorkItem(
IWorkItemsGroup workItemsGroup,
WorkItemInfo workItemInfo,
- WorkItemCallback callback,
+ WorkItemCallback callback,
object state)
{
_workItemsGroup = workItemsGroup;
_workItemInfo = workItemInfo;
+#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
if (_workItemInfo.UseCallerCallContext || _workItemInfo.UseCallerHttpContext)
{
_callerContext = CallerThreadContext.Capture(_workItemInfo.UseCallerCallContext, _workItemInfo.UseCallerHttpContext);
}
+#endif
_callback = callback;
_state = state;
@@ -222,9 +224,18 @@ namespace Amib.Threading.Internal
internal void Initialize()
{
+ // The _workItemState is changed directly instead of using the SetWorkItemState
+ // method since we don't want to go throught IsValidStateTransition.
_workItemState = WorkItemState.InQueue;
+
_workItemCompleted = null;
_workItemCompletedRefCount = 0;
+ _waitingOnQueueStopwatch = new Stopwatch();
+ _processingStopwatch = new Stopwatch();
+ _expirationTime =
+ _workItemInfo.Timeout > 0 ?
+ DateTime.UtcNow.Ticks + _workItemInfo.Timeout * TimeSpan.TicksPerMillisecond :
+ long.MaxValue;
}
internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
@@ -237,17 +248,16 @@ namespace Amib.Threading.Internal
#region Methods
- public CanceledWorkItemsGroup CanceledWorkItemsGroup
+ internal CanceledWorkItemsGroup CanceledWorkItemsGroup
{
- get
- {
- return _canceledWorkItemsGroup;
- }
+ get { return _canceledWorkItemsGroup; }
+ set { _canceledWorkItemsGroup = value; }
+ }
- set
- {
- _canceledWorkItemsGroup = value;
- }
+ internal CanceledWorkItemsGroup CanceledSmartThreadPool
+ {
+ get { return _canceledSmartThreadPool; }
+ set { _canceledSmartThreadPool = value; }
}
///
@@ -259,9 +269,10 @@ namespace Amib.Threading.Internal
///
public bool StartingWorkItem()
{
- _beginProcessTime = DateTime.Now;
+ _waitingOnQueueStopwatch.Stop();
+ _processingStopwatch.Start();
- lock(this)
+ lock (this)
{
if (IsCanceled)
{
@@ -277,6 +288,9 @@ namespace Amib.Threading.Internal
Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
+ // No need for a lock yet, only after the state has changed to InProgress
+ _executingThread = Thread.CurrentThread;
+
SetWorkItemState(WorkItemState.InProgress);
}
@@ -291,7 +305,7 @@ namespace Amib.Threading.Internal
CallToPostExecute currentCallToPostExecute = 0;
// Execute the work item if we are in the correct state
- switch(GetWorkItemState())
+ switch (GetWorkItemState())
{
case WorkItemState.InProgress:
currentCallToPostExecute |= CallToPostExecute.WhenWorkItemNotCanceled;
@@ -311,7 +325,7 @@ namespace Amib.Threading.Internal
PostExecute();
}
- _endProcessTime = DateTime.Now;
+ _processingStopwatch.Stop();
}
internal void FireWorkItemCompleted()
@@ -323,8 +337,21 @@ namespace Amib.Threading.Internal
_workItemCompletedEvent(this);
}
}
- catch // Ignore exceptions
- {}
+ catch // Suppress exceptions
+ { }
+ }
+
+ internal void FireWorkItemStarted()
+ {
+ try
+ {
+ if (null != _workItemStartedEvent)
+ {
+ _workItemStartedEvent(this);
+ }
+ }
+ catch // Suppress exceptions
+ { }
}
///
@@ -332,32 +359,70 @@ namespace Amib.Threading.Internal
///
private void ExecuteWorkItem()
{
+
+#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
CallerThreadContext ctc = null;
if (null != _callerContext)
{
ctc = CallerThreadContext.Capture(_callerContext.CapturedCallContext, _callerContext.CapturedHttpContext);
CallerThreadContext.Apply(_callerContext);
}
+#endif
Exception exception = null;
object result = null;
try
{
- result = _callback(_state);
+ try
+ {
+ result = _callback(_state);
+ }
+ catch (Exception e)
+ {
+ // Save the exception so we can rethrow it later
+ exception = e;
+ }
+
+ // Remove the value of the execution thread, so it will be impossible to cancel the work item,
+ // since it is already completed.
+ // Cancelling a work item that already completed may cause the abortion of the next work item!!!
+ Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
+
+ if (null == executionThread)
+ {
+ // Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException
+ Thread.Sleep(60 * 1000);
+
+ // If after 1 minute this thread was not aborted then let it continue working.
+ }
}
- catch (Exception e)
+ // We must treat the ThreadAbortException or else it will be stored in the exception variable
+ catch (ThreadAbortException tae)
{
- // Save the exception so we can rethrow it later
- exception = e;
+ tae.GetHashCode();
+ // Check if the work item was cancelled
+ // If we got a ThreadAbortException and the STP is not shutting down, it means the
+ // work items was cancelled.
+ if (!SmartThreadPool.CurrentThreadEntry.AssociatedSmartThreadPool.IsShuttingdown)
+ {
+#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
+ Thread.ResetAbort();
+#endif
+ }
}
-
+
+#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE)
if (null != _callerContext)
{
CallerThreadContext.Apply(ctc);
}
+#endif
- SetResult(result, exception);
+ if (!SmartThreadPool.IsWorkItemCanceled)
+ {
+ SetResult(result, exception);
+ }
}
///
@@ -369,9 +434,9 @@ namespace Amib.Threading.Internal
{
try
{
- _workItemInfo.PostExecuteWorkItemCallback(this._workItemResult);
+ _workItemInfo.PostExecuteWorkItemCallback(_workItemResult);
}
- catch (Exception e)
+ catch (Exception e)
{
Debug.Assert(null != e);
}
@@ -382,6 +447,8 @@ namespace Amib.Threading.Internal
/// Set the result of the work item to return
///
/// The result of the work item
+ /// The exception that was throw while the workitem executed, null
+ /// if there was no exception.
internal void SetResult(object result, Exception exception)
{
_result = result;
@@ -401,48 +468,48 @@ namespace Amib.Threading.Internal
///
/// Wait for all work items to complete
///
- /// Array of work item result objects
+ /// Array of work item result objects
/// The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.
///
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
///
/// A cancel wait handle to interrupt the wait if needed
///
- /// true when every work item in workItemResults has completed; otherwise false.
+ /// true when every work item in waitableResults has completed; otherwise false.
///
internal static bool WaitAll(
- IWorkItemResult [] workItemResults,
+ IWaitableResult[] waitableResults,
int millisecondsTimeout,
bool exitContext,
WaitHandle cancelWaitHandle)
{
- if (0 == workItemResults.Length)
+ if (0 == waitableResults.Length)
{
return true;
}
bool success;
- WaitHandle [] waitHandles = new WaitHandle[workItemResults.Length];;
- GetWaitHandles(workItemResults, waitHandles);
+ WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
+ GetWaitHandles(waitableResults, waitHandles);
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
{
- success = WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
+ success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
}
else
{
success = true;
int millisecondsLeft = millisecondsTimeout;
- DateTime start = DateTime.Now;
+ Stopwatch stopwatch = Stopwatch.StartNew();
- WaitHandle [] whs;
+ WaitHandle[] whs;
if (null != cancelWaitHandle)
{
- whs = new WaitHandle [] { null, cancelWaitHandle };
+ whs = new WaitHandle[] { null, cancelWaitHandle };
}
else
{
- whs = new WaitHandle [] { null };
+ whs = new WaitHandle[] { null };
}
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
@@ -450,7 +517,7 @@ namespace Amib.Threading.Internal
// We cannot use WaitHandle.WaitAll directly, because the cancelWaitHandle
// won't affect it.
// Each iteration we update the time left for the timeout.
- for(int i = 0; i < workItemResults.Length; ++i)
+ for (int i = 0; i < waitableResults.Length; ++i)
{
// WaitAny don't work with negative numbers
if (!waitInfinitely && (millisecondsLeft < 0))
@@ -460,23 +527,22 @@ namespace Amib.Threading.Internal
}
whs[0] = waitHandles[i];
- int result = WaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
- if((result > 0) || (WaitHandle.WaitTimeout == result))
+ int result = STPEventWaitHandle.WaitAny(whs, millisecondsLeft, exitContext);
+ if ((result > 0) || (STPEventWaitHandle.WaitTimeout == result))
{
success = false;
break;
}
- if(!waitInfinitely)
+ if (!waitInfinitely)
{
// Update the time left to wait
- TimeSpan ts = DateTime.Now - start;
- millisecondsLeft = millisecondsTimeout - (int)ts.TotalMilliseconds;
+ millisecondsLeft = millisecondsTimeout - (int)stopwatch.ElapsedMilliseconds;
}
}
}
// Release the wait handles
- ReleaseWaitHandles(workItemResults);
+ ReleaseWaitHandles(waitableResults);
return success;
}
@@ -484,7 +550,7 @@ namespace Amib.Threading.Internal
///
/// Waits for any of the work items in the specified array to complete, cancel, or timeout
///
- /// Array of work item result objects
+ /// Array of work item result objects
/// The number of milliseconds to wait, or Timeout.Infinite (-1) to wait indefinitely.
///
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
@@ -493,38 +559,38 @@ namespace Amib.Threading.Internal
///
/// 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.
///
- internal static int WaitAny(
- IWorkItemResult [] workItemResults,
+ internal static int WaitAny(
+ IWaitableResult[] waitableResults,
int millisecondsTimeout,
bool exitContext,
WaitHandle cancelWaitHandle)
{
- WaitHandle [] waitHandles = null;
+ WaitHandle[] waitHandles;
if (null != cancelWaitHandle)
{
- waitHandles = new WaitHandle[workItemResults.Length+1];
- GetWaitHandles(workItemResults, waitHandles);
- waitHandles[workItemResults.Length] = cancelWaitHandle;
+ waitHandles = new WaitHandle[waitableResults.Length + 1];
+ GetWaitHandles(waitableResults, waitHandles);
+ waitHandles[waitableResults.Length] = cancelWaitHandle;
}
else
{
- waitHandles = new WaitHandle[workItemResults.Length];
- GetWaitHandles(workItemResults, waitHandles);
+ waitHandles = new WaitHandle[waitableResults.Length];
+ GetWaitHandles(waitableResults, waitHandles);
}
- int result = WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
+ int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
// Treat cancel as timeout
if (null != cancelWaitHandle)
{
- if (result == workItemResults.Length)
+ if (result == waitableResults.Length)
{
- result = WaitHandle.WaitTimeout;
+ result = STPEventWaitHandle.WaitTimeout;
}
}
- ReleaseWaitHandles(workItemResults);
+ ReleaseWaitHandles(waitableResults);
return result;
}
@@ -532,16 +598,16 @@ namespace Amib.Threading.Internal
///
/// Fill an array of wait handles with the work items wait handles.
///
- /// An array of work item results
+ /// An array of work item results
/// An array of wait handles to fill
private static void GetWaitHandles(
- IWorkItemResult [] workItemResults,
- WaitHandle [] waitHandles)
+ IWaitableResult[] waitableResults,
+ WaitHandle[] waitHandles)
{
- for(int i = 0; i < workItemResults.Length; ++i)
+ for (int i = 0; i < waitableResults.Length; ++i)
{
- WorkItemResult wir = workItemResults[i] as WorkItemResult;
- Debug.Assert(null != wir, "All workItemResults must be WorkItemResult objects");
+ WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
+ Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects");
waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
}
@@ -550,40 +616,64 @@ namespace Amib.Threading.Internal
///
/// Release the work items' wait handles
///
- /// An array of work item results
- private static void ReleaseWaitHandles(IWorkItemResult [] workItemResults)
+ /// An array of work item results
+ private static void ReleaseWaitHandles(IWaitableResult[] waitableResults)
{
- for(int i = 0; i < workItemResults.Length; ++i)
+ for (int i = 0; i < waitableResults.Length; ++i)
{
- WorkItemResult wir = workItemResults[i] as WorkItemResult;
+ WorkItemResult wir = (WorkItemResult)waitableResults[i].GetWorkItemResult();
wir.GetWorkItem().ReleaseWaitHandle();
}
}
-
#endregion
-
+
#region Private Members
private WorkItemState GetWorkItemState()
{
- if (_canceledWorkItemsGroup.IsCanceled)
+ lock (this)
{
- return WorkItemState.Canceled;
- }
- return _workItemState;
+ if (WorkItemState.Completed == _workItemState)
+ {
+ return _workItemState;
+ }
+
+ long nowTicks = DateTime.UtcNow.Ticks;
+ if (WorkItemState.Canceled != _workItemState && nowTicks > _expirationTime)
+ {
+ _workItemState = WorkItemState.Canceled;
+ }
+
+ if (WorkItemState.InProgress == _workItemState)
+ {
+ return _workItemState;
+ }
+
+ if (CanceledSmartThreadPool.IsCanceled || CanceledWorkItemsGroup.IsCanceled)
+ {
+ return WorkItemState.Canceled;
+ }
+
+ return _workItemState;
+ }
}
+
+
///
/// Sets the work item's state
///
/// The state to set the work item to
private void SetWorkItemState(WorkItemState workItemState)
{
- lock(this)
+ lock (this)
{
- _workItemState = workItemState;
+ if (IsValidStatesTransition(_workItemState, workItemState))
+ {
+ _workItemState = workItemState;
+ }
}
}
@@ -594,7 +684,7 @@ namespace Amib.Threading.Internal
private void SignalComplete(bool canceled)
{
SetWorkItemState(canceled ? WorkItemState.Canceled : WorkItemState.Completed);
- lock(this)
+ lock (this)
{
// If someone is waiting then signal.
if (null != _workItemCompleted)
@@ -606,40 +696,93 @@ namespace Amib.Threading.Internal
internal void WorkItemIsQueued()
{
- _queuedTime = DateTime.Now;
+ _waitingOnQueueStopwatch.Start();
}
#endregion
-
+
#region Members exposed by WorkItemResult
///
/// Cancel the work item if it didn't start running yet.
///
/// Returns true on success or false if the work item is in progress or already completed
- private bool Cancel()
+ private bool Cancel(bool abortExecution)
{
- lock(this)
+#if (_WINDOWS_CE)
+ if(abortExecution)
+ {
+ throw new ArgumentOutOfRangeException("abortExecution", "WindowsCE doesn't support this feature");
+ }
+#endif
+ bool success = false;
+ bool signalComplete = false;
+
+ lock (this)
{
- switch(GetWorkItemState())
+ switch (GetWorkItemState())
{
case WorkItemState.Canceled:
//Debug.WriteLine("Work item already canceled");
- return true;
+ if (abortExecution)
+ {
+ Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
+ if (null != executionThread)
+ {
+ executionThread.Abort(); // "Cancel"
+ // No need to signalComplete, because we already cancelled this work item
+ // so it already signaled its completion.
+ //signalComplete = true;
+ }
+ }
+ success = true;
+ break;
case WorkItemState.Completed:
- case WorkItemState.InProgress:
//Debug.WriteLine("Work item cannot be canceled");
- return false;
+ break;
+ case WorkItemState.InProgress:
+ if (abortExecution)
+ {
+ Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
+ if (null != executionThread)
+ {
+ executionThread.Abort(); // "Cancel"
+ success = true;
+ signalComplete = true;
+ }
+ }
+ else
+ {
+ // **************************
+ // Stock SmartThreadPool 2.2.3 sets these to true and relies on the thread to check the
+ // WorkItem cancellation status. However, OpenSimulator uses a different mechanism to notify
+ // scripts of co-operative termination and the abort code also relies on this method
+ // returning false in order to implement a small wait.
+ //
+ // Therefore, as was the case previously with STP, we will not signal successful cancellation
+ // here. It's possible that OpenSimulator code could be changed in the future to remove
+ // the need for this change.
+ // **************************
+ success = false;
+ signalComplete = false;
+ }
+ break;
case WorkItemState.InQueue:
// Signal to the wait for completion that the work
// item has been completed (canceled). There is no
// reason to wait for it to get out of the queue
- SignalComplete(true);
+ signalComplete = true;
//Debug.WriteLine("Work item canceled");
- return true;
+ success = true;
+ break;
+ }
+
+ if (signalComplete)
+ {
+ SignalComplete(true);
}
}
- return false;
+ return success;
}
///
@@ -653,7 +796,7 @@ namespace Amib.Threading.Internal
bool exitContext,
WaitHandle cancelWaitHandle)
{
- Exception e = null;
+ Exception e;
object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
if (null != e)
{
@@ -694,7 +837,7 @@ namespace Amib.Threading.Internal
{
WaitHandle wh = GetWaitHandle();
- bool timeout = !wh.WaitOne(millisecondsTimeout, exitContext);
+ bool timeout = !STPEventWaitHandle.WaitOne(wh, millisecondsTimeout, exitContext);
ReleaseWaitHandle();
@@ -706,10 +849,10 @@ namespace Amib.Threading.Internal
else
{
WaitHandle wh = GetWaitHandle();
- int result = WaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
+ int result = STPEventWaitHandle.WaitAny(new WaitHandle[] { wh, cancelWaitHandle });
ReleaseWaitHandle();
- switch(result)
+ switch (result)
{
case 0:
// The work item signaled
@@ -717,7 +860,7 @@ namespace Amib.Threading.Internal
// work item (not the get result)
break;
case 1:
- case WaitHandle.WaitTimeout:
+ case STPEventWaitHandle.WaitTimeout:
throw new WorkItemTimeoutException("Work item timeout");
default:
Debug.Assert(false);
@@ -745,11 +888,11 @@ namespace Amib.Threading.Internal
///
private WaitHandle GetWaitHandle()
{
- lock(this)
+ lock (this)
{
if (null == _workItemCompleted)
{
- _workItemCompleted = new ManualResetEvent(IsCompleted);
+ _workItemCompleted = EventWaitHandleFactory.CreateManualResetEvent(IsCompleted);
}
++_workItemCompletedRefCount;
}
@@ -758,7 +901,7 @@ namespace Amib.Threading.Internal
private void ReleaseWaitHandle()
{
- lock(this)
+ lock (this)
{
if (null != _workItemCompleted)
{
@@ -779,10 +922,10 @@ namespace Amib.Threading.Internal
{
get
{
- lock(this)
+ lock (this)
{
WorkItemState workItemState = GetWorkItemState();
- return ((workItemState == WorkItemState.Completed) ||
+ return ((workItemState == WorkItemState.Completed) ||
(workItemState == WorkItemState.Canceled));
}
}
@@ -795,7 +938,7 @@ namespace Amib.Threading.Internal
{
get
{
- lock(this)
+ lock (this)
{
return (GetWorkItemState() == WorkItemState.Canceled);
}
@@ -843,172 +986,6 @@ namespace Amib.Threading.Internal
}
}
-
- #region WorkItemResult class
-
- private class WorkItemResult : IWorkItemResult, IInternalWorkItemResult
- {
- ///
- /// A back reference to the work item
- ///
- private WorkItem _workItem;
-
- public WorkItemResult(WorkItem workItem)
- {
- _workItem = workItem;
- }
-
- internal WorkItem GetWorkItem()
- {
- return _workItem;
- }
-
- #region IWorkItemResult Members
-
- public bool IsCompleted
- {
- get
- {
- return _workItem.IsCompleted;
- }
- }
-
- public void Abort()
- {
- _workItem.Abort();
- }
-
- public bool IsCanceled
- {
- get
- {
- return _workItem.IsCanceled;
- }
- }
-
- public object GetResult()
- {
- return _workItem.GetResult(Timeout.Infinite, true, null);
- }
-
- public object GetResult(int millisecondsTimeout, bool exitContext)
- {
- return _workItem.GetResult(millisecondsTimeout, exitContext, null);
- }
-
- public object GetResult(TimeSpan timeout, bool exitContext)
- {
- return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null);
- }
-
- public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle)
- {
- return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle);
- }
-
- public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle)
- {
- return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle);
- }
-
- public object GetResult(out Exception e)
- {
- return _workItem.GetResult(Timeout.Infinite, true, null, out e);
- }
-
- public object GetResult(int millisecondsTimeout, bool exitContext, out Exception e)
- {
- return _workItem.GetResult(millisecondsTimeout, exitContext, null, out e);
- }
-
- public object GetResult(TimeSpan timeout, bool exitContext, out Exception e)
- {
- return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, null, out e);
- }
-
- public object GetResult(int millisecondsTimeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
- {
- return _workItem.GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
- }
-
- public object GetResult(TimeSpan timeout, bool exitContext, WaitHandle cancelWaitHandle, out Exception e)
- {
- return _workItem.GetResult((int)timeout.TotalMilliseconds, exitContext, cancelWaitHandle, out e);
- }
-
- public bool Cancel()
- {
- return _workItem.Cancel();
- }
-
- public object State
- {
- get
- {
- return _workItem._state;
- }
- }
-
- public WorkItemPriority WorkItemPriority
- {
- get
- {
- return _workItem._workItemInfo.WorkItemPriority;
- }
- }
-
- ///
- /// Return the result, same as GetResult()
- ///
- public object Result
- {
- get { return GetResult(); }
- }
-
- ///
- /// Returns the exception if occured otherwise returns null.
- /// This value is valid only after the work item completed,
- /// before that it is always null.
- ///
- public object Exception
- {
- get { return _workItem._exception; }
- }
-
- #endregion
-
- #region IInternalWorkItemResult Members
-
- public event WorkItemStateCallback OnWorkItemStarted
- {
- add
- {
- _workItem.OnWorkItemStarted += value;
- }
- remove
- {
- _workItem.OnWorkItemStarted -= value;
- }
- }
-
-
- public event WorkItemStateCallback OnWorkItemCompleted
- {
- add
- {
- _workItem.OnWorkItemCompleted += value;
- }
- remove
- {
- _workItem.OnWorkItemCompleted -= value;
- }
- }
-
- #endregion
- }
-
- #endregion
-
public void DisposeOfState()
{
if (_workItemInfo.DisposeOfStateObjects)
@@ -1021,15 +998,5 @@ namespace Amib.Threading.Internal
}
}
}
-
- public void Abort()
- {
- lock (this)
- {
- if(currentThread != null)
- currentThread.Abort();
- }
- }
}
- #endregion
}
--
cgit v1.1