SpawningAsyncTaskMethodBuilder
When applied to async method using AsyncMethodBuilderAttribute attribute,
spawns method execution as a new work item in the thread pool, i.e. in parallel.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
namespace DotNext.Runtime.CompilerServices
{
[StructLayout(LayoutKind.Auto)]
[NullableContext(1)]
[Nullable(0)]
public struct SpawningAsyncTaskMethodBuilder
{
private sealed class SpecialCallbackDetector : IValueTaskSource
{
void IValueTaskSource.GetResult(short token)
{
}
ValueTaskSourceStatus IValueTaskSource.GetStatus(short token)
{
return ValueTaskSourceStatus.Pending;
}
void IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
{
capturedArgs = (continuation, state);
}
}
internal static readonly ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter Awaiter = new ValueTask(new SpecialCallbackDetector(), 0).ConfigureAwait(false).GetAwaiter();
[ThreadStatic]
private static (Action<object> WorkItem, object State) capturedArgs;
private AsyncTaskMethodBuilder builder;
public Task Task => builder.Task;
public SpawningAsyncTaskMethodBuilder()
{
builder = AsyncTaskMethodBuilder.Create();
}
public static SpawningAsyncTaskMethodBuilder Create()
{
return new SpawningAsyncTaskMethodBuilder();
}
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter awaiter = Awaiter;
builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
Schedule();
}
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
{
builder.AwaitOnCompleted(ref awaiter, ref stateMachine);
}
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine
{
builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
}
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
builder.SetStateMachine(stateMachine);
}
public void SetResult()
{
builder.SetResult();
}
public void SetException(Exception e)
{
builder.SetException(e);
}
internal static void Schedule()
{
(Action<object> WorkItem, object State) valueTuple = capturedArgs;
Action<object> item = valueTuple.WorkItem;
object item2 = valueTuple.State;
capturedArgs = default((Action<object>, object));
ThreadPool.UnsafeQueueUserWorkItem(item, item2, false);
}
}
}