* Queue ValueTaskAwaiter IAsyncStateMachineBox directly to ThreadPool
* Invert the dependency
* Move to UnsafeQueueUserWorkItem
* MRVTSC queue null or Deafult EC to UnsafeQUWI
* Revert MRVTSC change
* Add comment and validation
* Use s_invokeAsyncStateMachineBox for AsTask
* nits
* nits 2
* Rever ValueTask
* nits
Commit migrated from https://github.com/dotnet/coreclr/commit/
e7ead79fedc52e17f2cf9befd5c0f5091d70f909
public static bool enableWorkerTracking;
public static readonly ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue();
+
+ /// <summary>Shim used to invoke <see cref="IAsyncStateMachineBox.MoveNext"/> of the supplied <see cref="IAsyncStateMachineBox"/>.</summary>
+ internal static readonly Action<object> s_invokeAsyncStateMachineBox = state =>
+ {
+ if (!(state is IAsyncStateMachineBox box))
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.state);
+ return;
+ }
+
+ box.MoveNext();
+ };
}
[StructLayout(LayoutKind.Sequential)] // enforce layout so that padding reduces false sharing
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.callBack);
}
+ // If the callback is the runtime-provided invocation of an IAsyncStateMachineBox,
+ // then we can queue the Task state directly to the ThreadPool instead of
+ // wrapping it in a QueueUserWorkItemCallback.
+ //
+ // This occurs when user code queues its provided continuation to the ThreadPool;
+ // internally we call UnsafeQueueUserWorkItemInternal directly for Tasks.
+ if (ReferenceEquals(callBack, ThreadPoolGlobals.s_invokeAsyncStateMachineBox))
+ {
+ if (!(state is IAsyncStateMachineBox))
+ {
+ // The provided state must be the internal IAsyncStateMachineBox (Task) type
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.state);
+ }
+
+ UnsafeQueueUserWorkItemInternal((object)state, preferLocal);
+ return true;
+ }
+
EnsureVMInitialized();
ThreadPoolGlobals.workQueue.Enqueue(
using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
}
else if (obj != null)
{
- Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token,
_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
}
else if (obj != null)
{
- Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token,
_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
}
else if (obj != null)
{
- Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, continueOnCapturedContext: true);
}
}
-
- /// <summary>Shim used to invoke <see cref="ITaskCompletionAction.Invoke"/> of the supplied <see cref="IAsyncStateMachineBox"/>.</summary>
- internal static readonly Action<object> s_invokeAsyncStateMachineBox = state =>
- {
- if (!(state is IAsyncStateMachineBox box))
- {
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.state);
- return;
- }
-
- box.MoveNext();
- };
#endif
}
}
else if (obj != null)
{
- Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ThreadPoolGlobals.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{