cosmetics
This commit is contained in:
@@ -43,12 +43,12 @@ namespace OSHttpServer
|
|||||||
/// Use a Thread or a Timer to monitor the ugly
|
/// Use a Thread or a Timer to monitor the ugly
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Thread m_internalThread = null;
|
private static Thread m_internalThread = null;
|
||||||
private static object m_threadLock = new object();
|
private static readonly object m_threadLock = new();
|
||||||
private static ConcurrentQueue<HttpClientContext> m_contexts = new ConcurrentQueue<HttpClientContext>();
|
private static readonly ConcurrentQueue<HttpClientContext> m_contexts = new();
|
||||||
private static ConcurrentQueue<HttpClientContext> m_highPrio = new ConcurrentQueue<HttpClientContext>();
|
private static readonly ConcurrentQueue<HttpClientContext> m_highPrio = new();
|
||||||
private static ConcurrentQueue<HttpClientContext> m_midPrio = new ConcurrentQueue<HttpClientContext>();
|
private static readonly ConcurrentQueue<HttpClientContext> m_midPrio = new();
|
||||||
private static ConcurrentQueue<HttpClientContext> m_lowPrio = new ConcurrentQueue<HttpClientContext>();
|
private static readonly ConcurrentQueue<HttpClientContext> m_lowPrio = new();
|
||||||
private static AutoResetEvent m_processWaitEven = new AutoResetEvent(false);
|
private static AutoResetEvent m_processWaitEven = new(false);
|
||||||
private static bool m_shuttingDown;
|
private static bool m_shuttingDown;
|
||||||
|
|
||||||
private static int m_ActiveSendingCount;
|
private static int m_ActiveSendingCount;
|
||||||
@@ -100,7 +100,7 @@ namespace OSHttpServer
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
double now = GetTimeStamp();
|
double now = GetTimeStamp();
|
||||||
if(m_contexts.Count > 0)
|
if(!m_contexts.IsEmpty)
|
||||||
{
|
{
|
||||||
ProcessSendQueues();
|
ProcessSendQueues();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
internal class CanceledWorkItemsGroup
|
internal class CanceledWorkItemsGroup
|
||||||
{
|
{
|
||||||
public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
public readonly static CanceledWorkItemsGroup NotCanceledWorkItemsGroup = new();
|
||||||
|
|
||||||
public CanceledWorkItemsGroup()
|
public CanceledWorkItemsGroup()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
@@ -7,25 +8,25 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
public const int WaitTimeout = Timeout.Infinite;
|
public const int WaitTimeout = Timeout.Infinite;
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
{
|
{
|
||||||
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static int WaitAny(WaitHandle[] waitHandles)
|
internal static int WaitAny(WaitHandle[] waitHandles)
|
||||||
{
|
{
|
||||||
return WaitHandle.WaitAny(waitHandles);
|
return WaitHandle.WaitAny(waitHandles);
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
|
||||||
{
|
{
|
||||||
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
|
||||||
{
|
{
|
||||||
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
return waitHandle.WaitOne(millisecondsTimeout, exitContext);
|
||||||
|
|||||||
53
ThirdParty/SmartThreadPool/SmartThreadPool.cs
vendored
53
ThirdParty/SmartThreadPool/SmartThreadPool.cs
vendored
@@ -98,7 +98,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -335,9 +334,7 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="idleTimeout">Idle timeout in milliseconds</param>
|
/// <param name="idleTimeout">Idle timeout in milliseconds</param>
|
||||||
/// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
|
/// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
|
||||||
public SmartThreadPool(
|
public SmartThreadPool(int idleTimeout, int maxWorkerThreads)
|
||||||
int idleTimeout,
|
|
||||||
int maxWorkerThreads)
|
|
||||||
{
|
{
|
||||||
m_stpStartInfo = new STPStartInfo
|
m_stpStartInfo = new STPStartInfo
|
||||||
{
|
{
|
||||||
@@ -353,10 +350,7 @@ namespace Amib.Threading
|
|||||||
/// <param name="idleTimeout">Idle timeout in milliseconds</param>
|
/// <param name="idleTimeout">Idle timeout in milliseconds</param>
|
||||||
/// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
|
/// <param name="maxWorkerThreads">Upper limit of threads in the pool</param>
|
||||||
/// <param name="minWorkerThreads">Lower limit of threads in the pool</param>
|
/// <param name="minWorkerThreads">Lower limit of threads in the pool</param>
|
||||||
public SmartThreadPool(
|
public SmartThreadPool(int idleTimeout, int maxWorkerThreads, int minWorkerThreads)
|
||||||
int idleTimeout,
|
|
||||||
int maxWorkerThreads,
|
|
||||||
int minWorkerThreads)
|
|
||||||
{
|
{
|
||||||
m_stpStartInfo = new STPStartInfo
|
m_stpStartInfo = new STPStartInfo
|
||||||
{
|
{
|
||||||
@@ -445,10 +439,7 @@ namespace Amib.Threading
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
private WorkItem Dequeue()
|
private WorkItem Dequeue()
|
||||||
{
|
{
|
||||||
WorkItem workItem =
|
return m_workItemsQueue.DequeueWorkItem(m_stpStartInfo.IdleTimeout, m_shuttingDownEvent);
|
||||||
m_workItemsQueue.DequeueWorkItem(m_stpStartInfo.IdleTimeout, m_shuttingDownEvent);
|
|
||||||
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -458,7 +449,7 @@ namespace Amib.Threading
|
|||||||
internal override void Enqueue(WorkItem workItem)
|
internal override void Enqueue(WorkItem workItem)
|
||||||
{
|
{
|
||||||
// Make sure the workItem is not null
|
// Make sure the workItem is not null
|
||||||
Debug.Assert(null != workItem);
|
Debug.Assert(workItem is not null);
|
||||||
|
|
||||||
IncrementWorkItemsCount();
|
IncrementWorkItemsCount();
|
||||||
|
|
||||||
@@ -510,7 +501,7 @@ namespace Amib.Threading
|
|||||||
|
|
||||||
internal void UnregisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
|
internal void UnregisterWorkItemsGroup(IWorkItemsGroup workItemsGroup)
|
||||||
{
|
{
|
||||||
m_workItemsGroups.TryRemove(workItemsGroup.localID, out WorkItemsGroup dummy);
|
m_workItemsGroups.TryRemove(workItemsGroup.localID, out WorkItemsGroup _);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -519,10 +510,7 @@ namespace Amib.Threading
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void InformCompleted()
|
private void InformCompleted()
|
||||||
{
|
{
|
||||||
// There is no need to lock the two methods together
|
if (m_workerThreads.TryRemove(Environment.CurrentManagedThreadId, out ThreadEntry te))
|
||||||
// since only the current thread removes itself
|
|
||||||
// and the _workerThreads is a synchronized dictionary
|
|
||||||
if (m_workerThreads.TryRemove(Thread.CurrentThread.ManagedThreadId, out ThreadEntry te))
|
|
||||||
{
|
{
|
||||||
te.Clean();
|
te.Clean();
|
||||||
}
|
}
|
||||||
@@ -584,8 +572,7 @@ namespace Amib.Threading
|
|||||||
workerThread.SetApartmentState(m_stpStartInfo.ApartmentState);
|
workerThread.SetApartmentState(m_stpStartInfo.ApartmentState);
|
||||||
|
|
||||||
workerThread.Priority = m_stpStartInfo.ThreadPriority;
|
workerThread.Priority = m_stpStartInfo.ThreadPriority;
|
||||||
|
workerThread.Name = $"STP:{Name}:{m_threadCounter}";
|
||||||
workerThread.Name = string.Format("STP:{0}:{1}", Name, m_threadCounter);
|
|
||||||
|
|
||||||
Interlocked.Exchange(ref m_lastThreadCreateTS, DateTime.UtcNow.Ticks);
|
Interlocked.Exchange(ref m_lastThreadCreateTS, DateTime.UtcNow.Ticks);
|
||||||
++m_threadCounter;
|
++m_threadCounter;
|
||||||
@@ -606,7 +593,7 @@ namespace Amib.Threading
|
|||||||
{
|
{
|
||||||
// Keep the entry of the dictionary as thread's variable to avoid the synchronization locks
|
// Keep the entry of the dictionary as thread's variable to avoid the synchronization locks
|
||||||
// of the dictionary.
|
// of the dictionary.
|
||||||
CurrentThreadEntry = m_workerThreads[Thread.CurrentThread.ManagedThreadId];
|
CurrentThreadEntry = m_workerThreads[Environment.CurrentManagedThreadId];
|
||||||
|
|
||||||
bool informedCompleted = false;
|
bool informedCompleted = false;
|
||||||
FireOnThreadInitialization();
|
FireOnThreadInitialization();
|
||||||
@@ -646,7 +633,7 @@ namespace Amib.Threading
|
|||||||
WorkItem workItem = Dequeue();
|
WorkItem workItem = Dequeue();
|
||||||
|
|
||||||
// On timeout or shut down.
|
// On timeout or shut down.
|
||||||
if (workItem == null)
|
if (workItem is null)
|
||||||
{
|
{
|
||||||
// Double lock for quit.
|
// Double lock for quit.
|
||||||
if (m_workerThreads.Count > minworkers)
|
if (m_workerThreads.Count > minworkers)
|
||||||
@@ -753,7 +740,7 @@ namespace Amib.Threading
|
|||||||
*/
|
*/
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Assert(null != e);
|
Debug.Assert(e is not null);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -783,7 +770,7 @@ namespace Amib.Threading
|
|||||||
|
|
||||||
private void ValidateWaitForIdle()
|
private void ValidateWaitForIdle()
|
||||||
{
|
{
|
||||||
if (null != CurrentThreadEntry && CurrentThreadEntry.AssociatedSmartThreadPool == this)
|
if (CurrentThreadEntry is not null && CurrentThreadEntry.AssociatedSmartThreadPool == this)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException(
|
throw new NotSupportedException(
|
||||||
"WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
|
"WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
|
||||||
@@ -792,15 +779,15 @@ namespace Amib.Threading
|
|||||||
|
|
||||||
internal static void ValidateWorkItemsGroupWaitForIdle(IWorkItemsGroup workItemsGroup)
|
internal static void ValidateWorkItemsGroupWaitForIdle(IWorkItemsGroup workItemsGroup)
|
||||||
{
|
{
|
||||||
if (CurrentThreadEntry != null)
|
if (CurrentThreadEntry is not null)
|
||||||
ValidateWorkItemsGroupWaitForIdleImpl(workItemsGroup, CurrentThreadEntry.CurrentWorkItem);
|
ValidateWorkItemsGroupWaitForIdleImpl(workItemsGroup, CurrentThreadEntry.CurrentWorkItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private static void ValidateWorkItemsGroupWaitForIdleImpl(IWorkItemsGroup workItemsGroup, WorkItem workItem)
|
private static void ValidateWorkItemsGroupWaitForIdleImpl(IWorkItemsGroup workItemsGroup, WorkItem workItem)
|
||||||
{
|
{
|
||||||
if ((null != workItemsGroup) &&
|
if ((workItemsGroup is not null) &&
|
||||||
(null != workItem) &&
|
(workItem is not null) &&
|
||||||
workItem.WasQueuedBy(workItemsGroup))
|
workItem.WasQueuedBy(workItemsGroup))
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
|
throw new NotSupportedException("WaitForIdle cannot be called from a thread on its SmartThreadPool, it causes a deadlock");
|
||||||
@@ -855,7 +842,7 @@ namespace Amib.Threading
|
|||||||
// Each iteration we update the time left for the timeout.
|
// Each iteration we update the time left for the timeout.
|
||||||
foreach (ThreadEntry te in threadEntries)
|
foreach (ThreadEntry te in threadEntries)
|
||||||
{
|
{
|
||||||
if (te == null)
|
if (te is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Thread thread = te.WorkThread;
|
Thread thread = te.WorkThread;
|
||||||
@@ -889,11 +876,11 @@ namespace Amib.Threading
|
|||||||
// Abort the threads in the pool
|
// Abort the threads in the pool
|
||||||
foreach (ThreadEntry te in threadEntries)
|
foreach (ThreadEntry te in threadEntries)
|
||||||
{
|
{
|
||||||
if (te == null)
|
if (te is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Thread thread = te.WorkThread;
|
Thread thread = te.WorkThread;
|
||||||
if ((thread != null) && thread.IsAlive )
|
if (thread is not null && thread.IsAlive )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1310,14 +1297,14 @@ namespace Amib.Threading
|
|||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null != m_shuttingDownEvent)
|
if (m_shuttingDownEvent is not null)
|
||||||
{
|
{
|
||||||
m_shuttingDownEvent.Close();
|
m_shuttingDownEvent.Close();
|
||||||
m_shuttingDownEvent = null;
|
m_shuttingDownEvent = null;
|
||||||
}
|
}
|
||||||
m_workerThreads.Clear();
|
m_workerThreads.Clear();
|
||||||
|
|
||||||
if (null != m_isIdleWaitHandle)
|
if (m_isIdleWaitHandle is not null)
|
||||||
{
|
{
|
||||||
m_isIdleWaitHandle.Close();
|
m_isIdleWaitHandle.Close();
|
||||||
m_isIdleWaitHandle = null;
|
m_isIdleWaitHandle = null;
|
||||||
@@ -1418,7 +1405,7 @@ namespace Amib.Threading
|
|||||||
if(threadEntry.AssociatedSmartThreadPool == this)
|
if(threadEntry.AssociatedSmartThreadPool == this)
|
||||||
{
|
{
|
||||||
WorkItem workItem = threadEntry.CurrentWorkItem;
|
WorkItem workItem = threadEntry.CurrentWorkItem;
|
||||||
if (null != workItem && !workItem.IsCanceled)
|
if (workItem is not null && !workItem.IsCanceled)
|
||||||
{
|
{
|
||||||
threadEntry.CurrentWorkItem.GetWorkItemResult().Cancel(true);
|
threadEntry.CurrentWorkItem.GetWorkItemResult().Cancel(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
@@ -108,7 +106,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _workItem._state;
|
return _workItem.m_state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +125,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public object Exception
|
public object Exception
|
||||||
{
|
{
|
||||||
get { return _workItem._exception; }
|
get { return _workItem.m_exception; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
293
ThirdParty/SmartThreadPool/WorkItem.cs
vendored
293
ThirdParty/SmartThreadPool/WorkItem.cs
vendored
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
@@ -54,92 +54,92 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Callback delegate for the callback.
|
/// Callback delegate for the callback.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItemCallback _callback;
|
private WorkItemCallback m_callback;
|
||||||
private WaitCallback _callbackNoResult;
|
private WaitCallback m_callbackNoResult;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// State with which to call the callback delegate.
|
/// State with which to call the callback delegate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object _state;
|
private object m_state;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stores the caller's context
|
/// Stores the caller's context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ExecutionContext _callerContext = null;
|
private ExecutionContext m_callerContext = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds the result of the mehtod
|
/// Holds the result of the mehtod
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private object _result;
|
private object m_result;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hold the exception if the method threw it
|
/// Hold the exception if the method threw it
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Exception _exception;
|
private Exception m_exception;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hold the state of the work item
|
/// Hold the state of the work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private WorkItemState _workItemState;
|
private WorkItemState m_workItemState;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A ManualResetEvent to indicate that the result is ready
|
/// A ManualResetEvent to indicate that the result is ready
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ManualResetEvent _workItemCompleted;
|
private ManualResetEvent m_workItemCompleted;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference count to the _workItemCompleted.
|
/// A reference count to the _workItemCompleted.
|
||||||
/// When it reaches to zero _workItemCompleted is Closed
|
/// When it reaches to zero _workItemCompleted is Closed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _workItemCompletedRefCount;
|
private int m_workItemCompletedRefCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the result state of the work item
|
/// Represents the result state of the work item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly WorkItemResult _workItemResult;
|
private readonly WorkItemResult m_workItemResult;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work item info
|
/// Work item info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly WorkItemInfo _workItemInfo;
|
private readonly WorkItemInfo m_workItemInfo;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the WorkItem starts
|
/// Called when the WorkItem starts
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private event WorkItemStateCallback _workItemStartedEvent;
|
private event WorkItemStateCallback m_workItemStartedEvent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the WorkItem completes
|
/// Called when the WorkItem completes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private event WorkItemStateCallback _workItemCompletedEvent;
|
private event WorkItemStateCallback m_workItemCompletedEvent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to an object that indicates whatever the
|
/// A reference to an object that indicates whatever the
|
||||||
/// WorkItemsGroup has been canceled
|
/// WorkItemsGroup has been canceled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private CanceledWorkItemsGroup _canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
private CanceledWorkItemsGroup m_canceledWorkItemsGroup = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to an object that indicates whatever the
|
/// A reference to an object that indicates whatever the
|
||||||
/// SmartThreadPool has been canceled
|
/// SmartThreadPool has been canceled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private CanceledWorkItemsGroup _canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
private CanceledWorkItemsGroup m_canceledSmartThreadPool = CanceledWorkItemsGroup.NotCanceledWorkItemsGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The work item group this work item belong to.
|
/// The work item group this work item belong to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IWorkItemsGroup _workItemsGroup;
|
private readonly IWorkItemsGroup m_workItemsGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The thread that executes this workitem.
|
/// 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.
|
/// This field is available for the period when the work item is executed, before and after it is null.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Thread _executingThread;
|
private Thread m_executingThread;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absulote time when the work item will be timeout
|
/// The absulote time when the work item will be timeout
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private long _expirationTime;
|
private long m_expirationTime;
|
||||||
|
|
||||||
#region Performance Counter fields
|
#region Performance Counter fields
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _workItemInfo;
|
return m_workItemInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,42 +199,46 @@ namespace Amib.Threading.Internal
|
|||||||
/// that meant to run the callback
|
/// that meant to run the callback
|
||||||
public WorkItem(IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
|
public WorkItem(IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
|
||||||
{
|
{
|
||||||
_workItemsGroup = workItemsGroup;
|
m_workItemsGroup = workItemsGroup;
|
||||||
_workItemInfo = workItemInfo;
|
m_workItemInfo = workItemInfo;
|
||||||
|
|
||||||
if (_workItemInfo.UseCallerCallContext && !ExecutionContext.IsFlowSuppressed())
|
if (m_workItemInfo.UseCallerCallContext && !ExecutionContext.IsFlowSuppressed())
|
||||||
{
|
{
|
||||||
ExecutionContext ec = ExecutionContext.Capture();
|
ExecutionContext ec = ExecutionContext.Capture();
|
||||||
if (ec != null)
|
if (ec is not null)
|
||||||
_callerContext = ec.CreateCopy();
|
{
|
||||||
ec.Dispose();
|
m_callerContext = ec.CreateCopy();
|
||||||
ec = null;
|
ec.Dispose();
|
||||||
|
ec = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_callback = callback;
|
m_callback = callback;
|
||||||
_callbackNoResult = null;
|
m_callbackNoResult = null;
|
||||||
_state = state;
|
m_state = state;
|
||||||
_workItemResult = new WorkItemResult(this);
|
m_workItemResult = new WorkItemResult(this);
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkItem(IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, WaitCallback callback, object state)
|
public WorkItem(IWorkItemsGroup workItemsGroup, WorkItemInfo workItemInfo, WaitCallback callback, object state)
|
||||||
{
|
{
|
||||||
_workItemsGroup = workItemsGroup;
|
m_workItemsGroup = workItemsGroup;
|
||||||
_workItemInfo = workItemInfo;
|
m_workItemInfo = workItemInfo;
|
||||||
|
|
||||||
if (_workItemInfo.UseCallerCallContext && !ExecutionContext.IsFlowSuppressed())
|
if (m_workItemInfo.UseCallerCallContext && !ExecutionContext.IsFlowSuppressed())
|
||||||
{
|
{
|
||||||
ExecutionContext ec = ExecutionContext.Capture();
|
ExecutionContext ec = ExecutionContext.Capture();
|
||||||
if (ec != null)
|
if (ec is not null)
|
||||||
_callerContext = ec.CreateCopy();
|
{
|
||||||
ec.Dispose();
|
m_callerContext = ec.CreateCopy();
|
||||||
ec = null;
|
ec.Dispose();
|
||||||
|
ec = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_callbackNoResult = callback;
|
m_callbackNoResult = callback;
|
||||||
_state = state;
|
m_state = state;
|
||||||
_workItemResult = new WorkItemResult(this);
|
m_workItemResult = new WorkItemResult(this);
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,18 +246,18 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
// The _workItemState is changed directly instead of using the SetWorkItemState
|
// The _workItemState is changed directly instead of using the SetWorkItemState
|
||||||
// method since we don't want to go throught IsValidStateTransition.
|
// method since we don't want to go throught IsValidStateTransition.
|
||||||
_workItemState = WorkItemState.InQueue;
|
m_workItemState = WorkItemState.InQueue;
|
||||||
|
|
||||||
_workItemCompleted = null;
|
m_workItemCompleted = null;
|
||||||
_workItemCompletedRefCount = 0;
|
m_workItemCompletedRefCount = 0;
|
||||||
_waitingOnQueueStopwatch = new Stopwatch();
|
_waitingOnQueueStopwatch = new Stopwatch();
|
||||||
_processingStopwatch = new Stopwatch();
|
_processingStopwatch = new Stopwatch();
|
||||||
_expirationTime = _workItemInfo.Timeout > 0 ? DateTime.UtcNow.Ticks + _workItemInfo.Timeout * TimeSpan.TicksPerMillisecond : long.MaxValue;
|
m_expirationTime = m_workItemInfo.Timeout > 0 ? DateTime.UtcNow.Ticks + m_workItemInfo.Timeout * TimeSpan.TicksPerMillisecond : long.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
|
internal bool WasQueuedBy(IWorkItemsGroup workItemsGroup)
|
||||||
{
|
{
|
||||||
return (workItemsGroup == _workItemsGroup);
|
return (workItemsGroup == m_workItemsGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -263,14 +267,14 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
internal CanceledWorkItemsGroup CanceledWorkItemsGroup
|
internal CanceledWorkItemsGroup CanceledWorkItemsGroup
|
||||||
{
|
{
|
||||||
get { return _canceledWorkItemsGroup; }
|
get { return m_canceledWorkItemsGroup; }
|
||||||
set { _canceledWorkItemsGroup = value; }
|
set { m_canceledWorkItemsGroup = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CanceledWorkItemsGroup CanceledSmartThreadPool
|
internal CanceledWorkItemsGroup CanceledSmartThreadPool
|
||||||
{
|
{
|
||||||
get { return _canceledSmartThreadPool; }
|
get { return m_canceledSmartThreadPool; }
|
||||||
set { _canceledSmartThreadPool = value; }
|
set { m_canceledSmartThreadPool = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -289,8 +293,8 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
if (IsCanceled)
|
if (IsCanceled)
|
||||||
{
|
{
|
||||||
if ((_workItemInfo.PostExecuteWorkItemCallback != null) &&
|
if ((m_workItemInfo.PostExecuteWorkItemCallback is not null) &&
|
||||||
((_workItemInfo.CallToPostExecute & CallToPostExecute.WhenWorkItemCanceled) == CallToPostExecute.WhenWorkItemCanceled))
|
((m_workItemInfo.CallToPostExecute & CallToPostExecute.WhenWorkItemCanceled) == CallToPostExecute.WhenWorkItemCanceled))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -301,7 +305,7 @@ namespace Amib.Threading.Internal
|
|||||||
Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
|
Debug.Assert(WorkItemState.InQueue == GetWorkItemState());
|
||||||
|
|
||||||
// No need for a lock yet, only after the state has changed to InProgress
|
// No need for a lock yet, only after the state has changed to InProgress
|
||||||
_executingThread = Thread.CurrentThread;
|
m_executingThread = Thread.CurrentThread;
|
||||||
|
|
||||||
SetWorkItemState(WorkItemState.InProgress);
|
SetWorkItemState(WorkItemState.InProgress);
|
||||||
}
|
}
|
||||||
@@ -332,7 +336,7 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run the post execute as needed
|
// Run the post execute as needed
|
||||||
if ((currentCallToPostExecute & _workItemInfo.CallToPostExecute) != 0)
|
if ((currentCallToPostExecute & m_workItemInfo.CallToPostExecute) != 0)
|
||||||
{
|
{
|
||||||
PostExecute();
|
PostExecute();
|
||||||
}
|
}
|
||||||
@@ -344,7 +348,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_workItemCompletedEvent?.Invoke(this);
|
m_workItemCompletedEvent?.Invoke(this);
|
||||||
}
|
}
|
||||||
catch // Suppress exceptions
|
catch // Suppress exceptions
|
||||||
{ }
|
{ }
|
||||||
@@ -354,7 +358,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_workItemStartedEvent?.Invoke(this);
|
m_workItemStartedEvent?.Invoke(this);
|
||||||
}
|
}
|
||||||
catch // Suppress exceptions
|
catch // Suppress exceptions
|
||||||
{ }
|
{ }
|
||||||
@@ -372,32 +376,24 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(_callbackNoResult == null)
|
if(m_callbackNoResult is null)
|
||||||
{
|
{
|
||||||
if(_callerContext == null)
|
if(m_callerContext is null)
|
||||||
result = _callback(_state);
|
result = m_callback(m_state);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ContextCallback _ccb = new ContextCallback( o =>
|
ContextCallback _ccb = new( o => { result =m_callback(o); });
|
||||||
{
|
ExecutionContext.Run(m_callerContext, _ccb, m_state);
|
||||||
result =_callback(o);
|
|
||||||
});
|
|
||||||
|
|
||||||
ExecutionContext.Run(_callerContext, _ccb, _state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_callerContext == null)
|
if (m_callerContext is null)
|
||||||
_callbackNoResult(_state);
|
m_callbackNoResult(m_state);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ContextCallback _ccb = new ContextCallback(o =>
|
ContextCallback _ccb = new(o => { m_callbackNoResult(o); });
|
||||||
{
|
ExecutionContext.Run(m_callerContext, _ccb, m_state);
|
||||||
_callbackNoResult(o);
|
|
||||||
});
|
|
||||||
|
|
||||||
ExecutionContext.Run(_callerContext, _ccb, _state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,9 +406,9 @@ namespace Amib.Threading.Internal
|
|||||||
// Remove the value of the execution thread, so it will be impossible to cancel the work item,
|
// Remove the value of the execution thread, so it will be impossible to cancel the work item,
|
||||||
// since it is already completed.
|
// since it is already completed.
|
||||||
// Cancelling a work item that already completed may cause the abortion of the next work item!!!
|
// Cancelling a work item that already completed may cause the abortion of the next work item!!!
|
||||||
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
Thread executionThread = Interlocked.CompareExchange(ref m_executingThread, null, m_executingThread);
|
||||||
|
|
||||||
if (null == executionThread)
|
if (executionThread is null)
|
||||||
{
|
{
|
||||||
// Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException
|
// Oops! we are going to be aborted..., Wait here so we can catch the ThreadAbortException
|
||||||
Thread.Sleep(60 * 1000);
|
Thread.Sleep(60 * 1000);
|
||||||
@@ -443,15 +439,15 @@ namespace Amib.Threading.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void PostExecute()
|
private void PostExecute()
|
||||||
{
|
{
|
||||||
if (null != _workItemInfo.PostExecuteWorkItemCallback)
|
if (m_workItemInfo.PostExecuteWorkItemCallback is not null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_workItemInfo.PostExecuteWorkItemCallback(_workItemResult);
|
m_workItemInfo.PostExecuteWorkItemCallback(m_workItemResult);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Debug.Assert(null != e);
|
Debug.Assert(e is not null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,8 +460,8 @@ namespace Amib.Threading.Internal
|
|||||||
/// if there was no exception.</param>
|
/// if there was no exception.</param>
|
||||||
internal void SetResult(object result, Exception exception)
|
internal void SetResult(object result, Exception exception)
|
||||||
{
|
{
|
||||||
_result = result;
|
m_result = result;
|
||||||
_exception = exception;
|
m_exception = exception;
|
||||||
SignalComplete(false);
|
SignalComplete(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,7 +471,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <returns>The work item result</returns>
|
/// <returns>The work item result</returns>
|
||||||
internal IWorkItemResult GetWorkItemResult()
|
internal IWorkItemResult GetWorkItemResult()
|
||||||
{
|
{
|
||||||
return _workItemResult;
|
return m_workItemResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -502,7 +498,7 @@ namespace Amib.Threading.Internal
|
|||||||
WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
|
WaitHandle[] waitHandles = new WaitHandle[waitableResults.Length];
|
||||||
GetWaitHandles(waitableResults, waitHandles);
|
GetWaitHandles(waitableResults, waitHandles);
|
||||||
|
|
||||||
if ((null == cancelWaitHandle) && (waitHandles.Length <= 64))
|
if ((cancelWaitHandle is null) && (waitHandles.Length <= 64))
|
||||||
{
|
{
|
||||||
success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
success = STPEventWaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
|
||||||
}
|
}
|
||||||
@@ -512,15 +508,9 @@ namespace Amib.Threading.Internal
|
|||||||
int millisecondsLeft = millisecondsTimeout;
|
int millisecondsLeft = millisecondsTimeout;
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
WaitHandle[] whs;
|
WaitHandle[] whs = cancelWaitHandle is null ?
|
||||||
if (null != cancelWaitHandle)
|
new WaitHandle[] { null } :
|
||||||
{
|
new WaitHandle[] { null, cancelWaitHandle };
|
||||||
whs = new WaitHandle[] { null, cancelWaitHandle };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
whs = new WaitHandle[] { null };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
|
bool waitInfinitely = (Timeout.Infinite == millisecondsTimeout);
|
||||||
// Iterate over the wait handles and wait for each one to complete.
|
// Iterate over the wait handles and wait for each one to complete.
|
||||||
@@ -569,15 +559,11 @@ namespace Amib.Threading.Internal
|
|||||||
/// <returns>
|
/// <returns>
|
||||||
/// 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.
|
/// 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.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
internal static int WaitAny(
|
internal static int WaitAny( IWaitableResult[] waitableResults, int millisecondsTimeout,
|
||||||
IWaitableResult[] waitableResults,
|
bool exitContext, WaitHandle cancelWaitHandle)
|
||||||
int millisecondsTimeout,
|
|
||||||
bool exitContext,
|
|
||||||
WaitHandle cancelWaitHandle)
|
|
||||||
{
|
{
|
||||||
WaitHandle[] waitHandles;
|
WaitHandle[] waitHandles;
|
||||||
|
if (cancelWaitHandle is not null)
|
||||||
if (null != cancelWaitHandle)
|
|
||||||
{
|
{
|
||||||
waitHandles = new WaitHandle[waitableResults.Length + 1];
|
waitHandles = new WaitHandle[waitableResults.Length + 1];
|
||||||
GetWaitHandles(waitableResults, waitHandles);
|
GetWaitHandles(waitableResults, waitHandles);
|
||||||
@@ -592,7 +578,7 @@ namespace Amib.Threading.Internal
|
|||||||
int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
int result = STPEventWaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
|
||||||
|
|
||||||
// Treat cancel as timeout
|
// Treat cancel as timeout
|
||||||
if (null != cancelWaitHandle)
|
if (cancelWaitHandle is not null)
|
||||||
{
|
{
|
||||||
if (result == waitableResults.Length)
|
if (result == waitableResults.Length)
|
||||||
{
|
{
|
||||||
@@ -610,14 +596,13 @@ namespace Amib.Threading.Internal
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="waitableResults">An array of work item results</param>
|
/// <param name="waitableResults">An array of work item results</param>
|
||||||
/// <param name="waitHandles">An array of wait handles to fill</param>
|
/// <param name="waitHandles">An array of wait handles to fill</param>
|
||||||
private static void GetWaitHandles(
|
private static void GetWaitHandles(IWaitableResult[] waitableResults,
|
||||||
IWaitableResult[] waitableResults,
|
|
||||||
WaitHandle[] waitHandles)
|
WaitHandle[] waitHandles)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < waitableResults.Length; ++i)
|
for (int i = 0; i < waitableResults.Length; ++i)
|
||||||
{
|
{
|
||||||
WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
|
WorkItemResult wir = waitableResults[i].GetWorkItemResult() as WorkItemResult;
|
||||||
Debug.Assert(null != wir, "All waitableResults must be WorkItemResult objects");
|
Debug.Assert(wir is not null, "All waitableResults must be WorkItemResult objects");
|
||||||
|
|
||||||
waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
|
waitHandles[i] = wir.GetWorkItem().GetWaitHandle();
|
||||||
}
|
}
|
||||||
@@ -645,23 +630,23 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (WorkItemState.Completed == _workItemState)
|
if (WorkItemState.Completed == m_workItemState)
|
||||||
{
|
{
|
||||||
return _workItemState;
|
return m_workItemState;
|
||||||
}
|
}
|
||||||
if (WorkItemState.Canceled != _workItemState && DateTime.UtcNow.Ticks > _expirationTime)
|
if (WorkItemState.Canceled != _workItemState && DateTime.UtcNow.Ticks > _expirationTime)
|
||||||
{
|
{
|
||||||
_workItemState = WorkItemState.Canceled;
|
m_workItemState = WorkItemState.Canceled;
|
||||||
return _workItemState;
|
return m_workItemState;
|
||||||
}
|
}
|
||||||
if(WorkItemState.InProgress != _workItemState)
|
if(WorkItemState.InProgress != m_workItemState)
|
||||||
{
|
{
|
||||||
if (CanceledSmartThreadPool.IsCanceled || CanceledWorkItemsGroup.IsCanceled)
|
if (CanceledSmartThreadPool.IsCanceled || CanceledWorkItemsGroup.IsCanceled)
|
||||||
{
|
{
|
||||||
return WorkItemState.Canceled;
|
return WorkItemState.Canceled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _workItemState;
|
return m_workItemState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,9 +659,9 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (IsValidStatesTransition(_workItemState, workItemState))
|
if (IsValidStatesTransition(m_workItemState, workItemState))
|
||||||
{
|
{
|
||||||
_workItemState = workItemState;
|
m_workItemState = workItemState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -691,10 +676,7 @@ namespace Amib.Threading.Internal
|
|||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
// If someone is waiting then signal.
|
// If someone is waiting then signal.
|
||||||
if (null != _workItemCompleted)
|
m_workItemCompleted?.Set();
|
||||||
{
|
|
||||||
_workItemCompleted.Set();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,8 +706,8 @@ namespace Amib.Threading.Internal
|
|||||||
//Debug.WriteLine("Work item already canceled");
|
//Debug.WriteLine("Work item already canceled");
|
||||||
if (abortExecution)
|
if (abortExecution)
|
||||||
{
|
{
|
||||||
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
Thread executionThread = Interlocked.CompareExchange(ref m_executingThread, null, m_executingThread);
|
||||||
if (null != executionThread)
|
if (executionThread is not null)
|
||||||
{
|
{
|
||||||
//executionThread.Abort(); // "Cancel"
|
//executionThread.Abort(); // "Cancel"
|
||||||
// No need to signalComplete, because we already cancelled this work item
|
// No need to signalComplete, because we already cancelled this work item
|
||||||
@@ -741,8 +723,8 @@ namespace Amib.Threading.Internal
|
|||||||
case WorkItemState.InProgress:
|
case WorkItemState.InProgress:
|
||||||
if (abortExecution)
|
if (abortExecution)
|
||||||
{
|
{
|
||||||
Thread executionThread = Interlocked.CompareExchange(ref _executingThread, null, _executingThread);
|
Thread executionThread = Interlocked.CompareExchange(ref m_executingThread, null, m_executingThread);
|
||||||
if (null != executionThread)
|
if (executionThread is not null)
|
||||||
{
|
{
|
||||||
//executionThread.Abort(); // "Cancel"
|
//executionThread.Abort(); // "Cancel"
|
||||||
success = true;
|
success = true;
|
||||||
@@ -789,14 +771,11 @@ namespace Amib.Threading.Internal
|
|||||||
/// In case of error the method throws and exception
|
/// In case of error the method throws and exception
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
private object GetResult(
|
private object GetResult(int millisecondsTimeout, bool exitContext,
|
||||||
int millisecondsTimeout,
|
|
||||||
bool exitContext,
|
|
||||||
WaitHandle cancelWaitHandle)
|
WaitHandle cancelWaitHandle)
|
||||||
{
|
{
|
||||||
Exception e;
|
object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out Exception e);
|
||||||
object result = GetResult(millisecondsTimeout, exitContext, cancelWaitHandle, out e);
|
if (e is not null)
|
||||||
if (null != e)
|
|
||||||
{
|
{
|
||||||
throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
|
throw new WorkItemResultException("The work item caused an excpetion, see the inner exception for details", e);
|
||||||
}
|
}
|
||||||
@@ -809,11 +788,8 @@ namespace Amib.Threading.Internal
|
|||||||
/// In case of error the e argument is filled with the exception
|
/// In case of error the e argument is filled with the exception
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The result of the work item</returns>
|
/// <returns>The result of the work item</returns>
|
||||||
private object GetResult(
|
private object GetResult( int millisecondsTimeout, bool exitContext,
|
||||||
int millisecondsTimeout,
|
WaitHandle cancelWaitHandle, out Exception e)
|
||||||
bool exitContext,
|
|
||||||
WaitHandle cancelWaitHandle,
|
|
||||||
out Exception e)
|
|
||||||
{
|
{
|
||||||
e = null;
|
e = null;
|
||||||
|
|
||||||
@@ -826,12 +802,12 @@ namespace Amib.Threading.Internal
|
|||||||
// Check for completion
|
// Check for completion
|
||||||
if (IsCompleted)
|
if (IsCompleted)
|
||||||
{
|
{
|
||||||
e = _exception;
|
e = m_exception;
|
||||||
return _result;
|
return m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no cancelWaitHandle is provided
|
// If no cancelWaitHandle is provided
|
||||||
if (null == cancelWaitHandle)
|
if (cancelWaitHandle is null)
|
||||||
{
|
{
|
||||||
WaitHandle wh = GetWaitHandle();
|
WaitHandle wh = GetWaitHandle();
|
||||||
|
|
||||||
@@ -875,10 +851,10 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
Debug.Assert(IsCompleted);
|
Debug.Assert(IsCompleted);
|
||||||
|
|
||||||
e = _exception;
|
e = m_exception;
|
||||||
|
|
||||||
// Return the result
|
// Return the result
|
||||||
return _result;
|
return m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -888,26 +864,26 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (null == _workItemCompleted)
|
if (m_workItemCompleted is null)
|
||||||
{
|
{
|
||||||
_workItemCompleted = new ManualResetEvent(IsCompleted);
|
m_workItemCompleted = new ManualResetEvent(IsCompleted);
|
||||||
}
|
}
|
||||||
++_workItemCompletedRefCount;
|
++m_workItemCompletedRefCount;
|
||||||
}
|
}
|
||||||
return _workItemCompleted;
|
return m_workItemCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseWaitHandle()
|
private void ReleaseWaitHandle()
|
||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (null != _workItemCompleted)
|
if (m_workItemCompleted is not null)
|
||||||
{
|
{
|
||||||
--_workItemCompletedRefCount;
|
--m_workItemCompletedRefCount;
|
||||||
if (0 == _workItemCompletedRefCount)
|
if (0 == m_workItemCompletedRefCount)
|
||||||
{
|
{
|
||||||
_workItemCompleted.Close();
|
m_workItemCompleted.Close();
|
||||||
_workItemCompleted = null;
|
m_workItemCompleted = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -949,11 +925,11 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
add
|
add
|
||||||
{
|
{
|
||||||
_workItemStartedEvent += value;
|
m_workItemStartedEvent += value;
|
||||||
}
|
}
|
||||||
remove
|
remove
|
||||||
{
|
{
|
||||||
_workItemStartedEvent -= value;
|
m_workItemStartedEvent -= value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -961,39 +937,38 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
add
|
add
|
||||||
{
|
{
|
||||||
_workItemCompletedEvent += value;
|
m_workItemCompletedEvent += value;
|
||||||
}
|
}
|
||||||
remove
|
remove
|
||||||
{
|
{
|
||||||
_workItemCompletedEvent -= value;
|
m_workItemCompletedEvent -= value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeOfState()
|
public void DisposeOfState()
|
||||||
{
|
{
|
||||||
if(_callerContext != null)
|
if(m_callerContext is not null)
|
||||||
{
|
{
|
||||||
_callerContext.Dispose();
|
m_callerContext.Dispose();
|
||||||
_callerContext = null;
|
m_callerContext = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_workItemCompleted != null)
|
if(m_workItemCompleted is not null)
|
||||||
{
|
{
|
||||||
_workItemCompleted.Dispose();
|
m_workItemCompleted.Dispose();
|
||||||
_workItemCompleted = null;
|
m_workItemCompleted = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_workItemInfo.DisposeOfStateObjects)
|
if (m_workItemInfo.DisposeOfStateObjects)
|
||||||
{
|
{
|
||||||
IDisposable disp = _state as IDisposable;
|
if (m_state is IDisposable disp)
|
||||||
if (null != disp)
|
|
||||||
{
|
{
|
||||||
disp.Dispose();
|
disp.Dispose();
|
||||||
_state = null;
|
m_state = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_callback = null;
|
m_callback = null;
|
||||||
_callbackNoResult = null;
|
m_callbackNoResult = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
104
ThirdParty/SmartThreadPool/WorkItemFactory.cs
vendored
104
ThirdParty/SmartThreadPool/WorkItemFactory.cs
vendored
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
@@ -13,14 +15,8 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
||||||
|
return new WorkItem(workItemsGroup, new WorkItemInfo(workItemInfo), callback, state);
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
|
||||||
workItemsGroup,
|
|
||||||
new WorkItemInfo(workItemInfo),
|
|
||||||
callback,
|
|
||||||
state);
|
|
||||||
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorkItem CreateWorkItem(IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
public static WorkItem CreateWorkItem(IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
||||||
@@ -28,7 +24,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
|
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo()
|
WorkItemInfo workItemInfo = new()
|
||||||
{
|
{
|
||||||
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
||||||
PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback,
|
PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback,
|
||||||
@@ -36,12 +32,7 @@ namespace Amib.Threading.Internal
|
|||||||
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects,
|
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects,
|
||||||
};
|
};
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
return new WorkItem(workItemsGroup, workItemInfo, callback, state);
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
|
||||||
callback,
|
|
||||||
state);
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,6 +42,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <param name="wigStartInfo">Work item group start information</param>
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo, WorkItemCallback callback)
|
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo, WorkItemCallback callback)
|
||||||
{
|
{
|
||||||
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
|
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
|
||||||
@@ -64,15 +56,11 @@ namespace Amib.Threading.Internal
|
|||||||
/// <param name="workItemInfo">Work item info</param>
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
/// <param name="callback">A callback to execute</param>
|
/// <param name="callback">A callback to execute</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
||||||
WorkItemInfo workItemInfo, WorkItemCallback callback)
|
WorkItemInfo workItemInfo, WorkItemCallback callback)
|
||||||
{
|
{
|
||||||
return CreateWorkItem(
|
return CreateWorkItem(workItemsGroup, wigStartInfo, workItemInfo, callback, null);
|
||||||
workItemsGroup,
|
|
||||||
wigStartInfo,
|
|
||||||
workItemInfo,
|
|
||||||
callback,
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -85,12 +73,13 @@ namespace Amib.Threading.Internal
|
|||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
||||||
WorkItemCallback callback, object state)
|
WorkItemCallback callback, object state)
|
||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
|
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo()
|
WorkItemInfo workItemInfo = new()
|
||||||
{
|
{
|
||||||
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
||||||
PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback,
|
PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback,
|
||||||
@@ -98,12 +87,7 @@ namespace Amib.Threading.Internal
|
|||||||
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects,
|
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects,
|
||||||
};
|
};
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
return new WorkItem( workItemsGroup, workItemInfo, callback, state);
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
|
||||||
callback,
|
|
||||||
state);
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -117,13 +101,14 @@ namespace Amib.Threading.Internal
|
|||||||
/// The context object of the work item. Used for passing arguments to the work item.
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo, WorkItemInfo workItemInfo,
|
public static WorkItem CreateWorkItem( IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo, WorkItemInfo workItemInfo,
|
||||||
WorkItemCallback callback, object state)
|
WorkItemCallback callback, object state)
|
||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
WorkItem workItem = new(
|
||||||
workItemsGroup,
|
workItemsGroup,
|
||||||
new WorkItemInfo(workItemInfo),
|
new WorkItemInfo(workItemInfo),
|
||||||
callback,
|
callback,
|
||||||
@@ -145,29 +130,22 @@ namespace Amib.Threading.Internal
|
|||||||
/// A delegate to call after the callback completion
|
/// A delegate to call after the callback completion
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
public static WorkItem CreateWorkItem(
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
IWorkItemsGroup workItemsGroup,
|
public static WorkItem CreateWorkItem(IWorkItemsGroup workItemsGroup, WIGStartInfo wigStartInfo,
|
||||||
WIGStartInfo wigStartInfo,
|
WorkItemCallback callback, object state,PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
||||||
WorkItemCallback callback,
|
|
||||||
object state,
|
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
|
||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
WorkItemInfo workItemInfo = new()
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
{
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
||||||
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
PostExecuteWorkItemCallback = postExecuteWorkItemCallback,
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
CallToPostExecute = wigStartInfo.CallToPostExecute,
|
||||||
|
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects
|
||||||
|
};
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
return new WorkItem( workItemsGroup, workItemInfo, callback, state);
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
|
||||||
callback,
|
|
||||||
state);
|
|
||||||
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -184,35 +162,29 @@ namespace Amib.Threading.Internal
|
|||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
/// <returns>Returns a work item</returns>
|
/// <returns>Returns a work item</returns>
|
||||||
public static WorkItem CreateWorkItem(
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
IWorkItemsGroup workItemsGroup,
|
public static WorkItem CreateWorkItem(IWorkItemsGroup workItemsGroup,WIGStartInfo wigStartInfo,
|
||||||
WIGStartInfo wigStartInfo,
|
WorkItemCallback callback, object state,
|
||||||
WorkItemCallback callback,
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute)
|
||||||
object state,
|
|
||||||
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
|
||||||
CallToPostExecute callToPostExecute)
|
|
||||||
{
|
{
|
||||||
ValidateCallback(callback);
|
ValidateCallback(callback);
|
||||||
ValidateCallback(postExecuteWorkItemCallback);
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
WorkItemInfo workItemInfo = new WorkItemInfo();
|
WorkItemInfo workItemInfo = new()
|
||||||
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
{
|
||||||
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
UseCallerCallContext = wigStartInfo.UseCallerCallContext,
|
||||||
workItemInfo.CallToPostExecute = callToPostExecute;
|
PostExecuteWorkItemCallback = postExecuteWorkItemCallback,
|
||||||
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
CallToPostExecute = callToPostExecute,
|
||||||
|
DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects
|
||||||
|
};
|
||||||
|
|
||||||
WorkItem workItem = new WorkItem(
|
return new WorkItem(workItemsGroup, workItemInfo, callback, state);
|
||||||
workItemsGroup,
|
|
||||||
workItemInfo,
|
|
||||||
callback,
|
|
||||||
state);
|
|
||||||
|
|
||||||
return workItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void ValidateCallback(Delegate callback)
|
private static void ValidateCallback(Delegate callback)
|
||||||
{
|
{
|
||||||
if (callback != null && callback.GetInvocationList().Length > 1)
|
if (callback is not null && callback.GetInvocationList().Length > 1)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
|
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
|
||||||
}
|
}
|
||||||
|
|||||||
19
ThirdParty/SmartThreadPool/WorkItemsGroup.cs
vendored
19
ThirdParty/SmartThreadPool/WorkItemsGroup.cs
vendored
@@ -16,7 +16,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
#region Private members
|
#region Private members
|
||||||
|
|
||||||
private readonly object _lock = new object();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to the SmartThreadPool instance that created this
|
/// A reference to the SmartThreadPool instance that created this
|
||||||
@@ -67,22 +67,19 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signaled when all of the WorkItemsGroup's work item completed.
|
/// Signaled when all of the WorkItemsGroup's work item completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
private readonly ManualResetEvent _isIdleWaitHandle = new(true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A common object for all the work items that this work items group
|
/// A common object for all the work items that this work items group
|
||||||
/// generate so we can mark them to cancel in O(1)
|
/// generate so we can mark them to cancel in O(1)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Construction
|
#region Construction
|
||||||
|
|
||||||
public WorkItemsGroup(
|
public WorkItemsGroup(SmartThreadPool stp, int concurrency, WIGStartInfo wigStartInfo)
|
||||||
SmartThreadPool stp,
|
|
||||||
int concurrency,
|
|
||||||
WIGStartInfo wigStartInfo)
|
|
||||||
{
|
{
|
||||||
if (concurrency <= 0)
|
if (concurrency <= 0)
|
||||||
{
|
{
|
||||||
@@ -236,10 +233,8 @@ namespace Amib.Threading.Internal
|
|||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
|
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
|
||||||
{
|
{
|
||||||
if(null == onIdle)
|
if(onIdle is null)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
Delegate[] delegates = onIdle.GetInvocationList();
|
Delegate[] delegates = onIdle.GetInvocationList();
|
||||||
foreach(WorkItemsGroupIdleHandler eh in delegates)
|
foreach(WorkItemsGroupIdleHandler eh in delegates)
|
||||||
@@ -298,7 +293,7 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the work item is not null then enqueue it
|
// If the work item is not null then enqueue it
|
||||||
if (null != workItem)
|
if (workItem is not null)
|
||||||
{
|
{
|
||||||
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
|
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
|
||||||
|
|
||||||
@@ -323,7 +318,7 @@ namespace Amib.Threading.Internal
|
|||||||
_stp.UnregisterWorkItemsGroup(this);
|
_stp.UnregisterWorkItemsGroup(this);
|
||||||
IsIdle = true;
|
IsIdle = true;
|
||||||
_isIdleWaitHandle.Set();
|
_isIdleWaitHandle.Set();
|
||||||
if (decrementWorkItemsInStpQueue && _onIdle != null && _onIdle.GetInvocationList().Length > 0)
|
if (decrementWorkItemsInStpQueue && _onIdle is not null && _onIdle.GetInvocationList().Length > 0)
|
||||||
{
|
{
|
||||||
_stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
|
_stp.QueueWorkItem(new WorkItemCallback(FireOnIdle));
|
||||||
}
|
}
|
||||||
|
|||||||
57
ThirdParty/SmartThreadPool/WorkItemsQueue.cs
vendored
57
ThirdParty/SmartThreadPool/WorkItemsQueue.cs
vendored
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Amib.Threading.Internal
|
namespace Amib.Threading.Internal
|
||||||
{
|
{
|
||||||
@@ -16,7 +17,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waiters queue (implemented as stack).
|
/// Waiters queue (implemented as stack).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly WaiterEntry _headWaiterEntry = new WaiterEntry();
|
private readonly WaiterEntry _headWaiterEntry = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waiters count
|
/// Waiters count
|
||||||
@@ -26,7 +27,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Work items queue
|
/// Work items queue
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Queue<WorkItem> _workItems = new Queue<WorkItem>();
|
private readonly Queue<WorkItem> _workItems = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicate that work items are allowed to be queued
|
/// Indicate that work items are allowed to be queued
|
||||||
@@ -79,7 +80,7 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
// A work item cannot be null, since null is used in the
|
// A work item cannot be null, since null is used in the
|
||||||
// WaitForWorkItem() method to indicate timeout or cancel
|
// WaitForWorkItem() method to indicate timeout or cancel
|
||||||
if (workItem == null)
|
if (workItem is null)
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException("workItem", "workItem cannot be null");
|
throw new ArgumentNullException("workItem", "workItem cannot be null");
|
||||||
}
|
}
|
||||||
@@ -112,7 +113,7 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
public void CloseThreadWaiter()
|
public void CloseThreadWaiter()
|
||||||
{
|
{
|
||||||
if(_waiterEntry != null)
|
if(_waiterEntry is not null)
|
||||||
{
|
{
|
||||||
_waiterEntry.Close();
|
_waiterEntry.Close();
|
||||||
_waiterEntry = null;
|
_waiterEntry = null;
|
||||||
@@ -187,8 +188,7 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
// On success return the work item
|
// On success return the work item
|
||||||
WorkItem workItem = waiterEntry.WorkItem;
|
WorkItem workItem = waiterEntry.WorkItem;
|
||||||
if (workItem == null)
|
workItem ??= _workItems.Dequeue();
|
||||||
workItem = _workItems.Dequeue();
|
|
||||||
|
|
||||||
return workItem;
|
return workItem;
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// objects each thread has its own WaiterEntry object.
|
/// objects each thread has its own WaiterEntry object.
|
||||||
private static WaiterEntry GetThreadWaiterEntry()
|
private static WaiterEntry GetThreadWaiterEntry()
|
||||||
{
|
{
|
||||||
if (_waiterEntry == null)
|
if (_waiterEntry is null)
|
||||||
{
|
{
|
||||||
_waiterEntry = new WaiterEntry();
|
_waiterEntry = new WaiterEntry();
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ namespace Amib.Threading.Internal
|
|||||||
RemoveWaiter(newWaiterEntry, false);
|
RemoveWaiter(newWaiterEntry, false);
|
||||||
|
|
||||||
// If the stack is empty then newWaiterEntry is the new head of the stack
|
// If the stack is empty then newWaiterEntry is the new head of the stack
|
||||||
if (null == _headWaiterEntry._nextWaiterEntry)
|
if (_headWaiterEntry._nextWaiterEntry is null)
|
||||||
{
|
{
|
||||||
_headWaiterEntry._nextWaiterEntry = newWaiterEntry;
|
_headWaiterEntry._nextWaiterEntry = newWaiterEntry;
|
||||||
newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
||||||
@@ -325,7 +325,7 @@ namespace Amib.Threading.Internal
|
|||||||
|
|
||||||
// Update the new stack head
|
// Update the new stack head
|
||||||
_headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
|
_headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
|
||||||
if (newHeadWaiterEntry != null)
|
if (newHeadWaiterEntry is not null)
|
||||||
{
|
{
|
||||||
newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
||||||
}
|
}
|
||||||
@@ -357,7 +357,7 @@ namespace Amib.Threading.Internal
|
|||||||
// If the waiter entry had a prev link then update it.
|
// If the waiter entry had a prev link then update it.
|
||||||
// It also means that the waiter is already in the list and we
|
// It also means that the waiter is already in the list and we
|
||||||
// need to decrement the waiters count.
|
// need to decrement the waiters count.
|
||||||
if (prevWaiterEntry != null)
|
if (prevWaiterEntry is not null)
|
||||||
{
|
{
|
||||||
prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
|
prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
|
||||||
popDecrement = true;
|
popDecrement = true;
|
||||||
@@ -366,7 +366,7 @@ namespace Amib.Threading.Internal
|
|||||||
// If the waiter entry had a next link then update it.
|
// If the waiter entry had a next link then update it.
|
||||||
// It also means that the waiter is already in the list and we
|
// It also means that the waiter is already in the list and we
|
||||||
// need to decrement the waiters count.
|
// need to decrement the waiters count.
|
||||||
if (nextWaiterEntry != null)
|
if (nextWaiterEntry is not null)
|
||||||
{
|
{
|
||||||
nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
|
nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
|
||||||
popDecrement = true;
|
popDecrement = true;
|
||||||
@@ -391,7 +391,7 @@ namespace Amib.Threading.Internal
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event to signal the waiter that it got the work item.
|
/// Event to signal the waiter that it got the work item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
|
private AutoResetEvent _waitHandle = new(false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag to know if this waiter already quited from the queue
|
/// Flag to know if this waiter already quited from the queue
|
||||||
@@ -450,15 +450,14 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
{
|
{
|
||||||
if (!_isTimedout)
|
if (_isTimedout)
|
||||||
{
|
return false;
|
||||||
_workItem = workItem;
|
|
||||||
_isSignaled = true;
|
_workItem = workItem;
|
||||||
_waitHandle.Set();
|
_isSignaled = true;
|
||||||
return true;
|
_waitHandle.Set();
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -472,15 +471,14 @@ namespace Amib.Threading.Internal
|
|||||||
{
|
{
|
||||||
// Time out can happen only if the waiter wasn't marked as
|
// Time out can happen only if the waiter wasn't marked as
|
||||||
// signaled
|
// signaled
|
||||||
if (!_isSignaled)
|
if (_isSignaled)
|
||||||
{
|
return false;
|
||||||
// We don't remove the waiter from the queue, the DequeueWorkItem
|
|
||||||
// method skips _waiters that were timed out.
|
// We don't remove the waiter from the queue, the DequeueWorkItem
|
||||||
_isTimedout = true;
|
// method skips _waiters that were timed out.
|
||||||
return true;
|
_isTimedout = true;
|
||||||
}
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -500,7 +498,7 @@ namespace Amib.Threading.Internal
|
|||||||
public void Close()
|
public void Close()
|
||||||
{
|
{
|
||||||
_workItem = null;
|
_workItem = null;
|
||||||
if (null != _waitHandle)
|
if (_waitHandle is not null)
|
||||||
{
|
{
|
||||||
_waitHandle.Close();
|
_waitHandle.Close();
|
||||||
_waitHandle = null;
|
_waitHandle = null;
|
||||||
@@ -546,6 +544,7 @@ namespace Amib.Threading.Internal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ValidateNotDisposed()
|
private void ValidateNotDisposed()
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
if (_isDisposed)
|
||||||
|
|||||||
Reference in New Issue
Block a user