cosmetics

This commit is contained in:
UbitUmarov
2023-03-07 14:33:42 +00:00
parent 048a321e33
commit ec39f85a7a
9 changed files with 242 additions and 315 deletions

View File

@@ -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();

View File

@@ -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()
{ {

View File

@@ -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);

View File

@@ -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);
} }

View File

@@ -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

View File

@@ -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;
} }
} }
} }

View File

@@ -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");
} }

View File

@@ -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));
} }

View File

@@ -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)