Skip to content

Commit 83cfc3c

Browse files
committed
Revert "Use .NET public API to spawn the async method execution"
This reverts commit 076c105.
1 parent ff94862 commit 83cfc3c

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

src/DotNext/Runtime/CompilerServices/SpawningTaskMethodBuilder.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Runtime.CompilerServices;
22
using System.Runtime.InteropServices;
3+
using System.Threading.Tasks.Sources;
34

45
namespace DotNext.Runtime.CompilerServices;
56

@@ -31,8 +32,9 @@ public struct SpawningAsyncTaskMethodBuilder<TResult>()
3132
public void Start<TStateMachine>(ref TStateMachine stateMachine)
3233
where TStateMachine : IAsyncStateMachine
3334
{
34-
var awaiter = System.Threading.Tasks.Task.Yield().GetAwaiter();
35+
var awaiter = SpawningAsyncTaskMethodBuilder.Awaiter;
3536
builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
37+
SpawningAsyncTaskMethodBuilder.Schedule();
3638
}
3739

3840
/// <summary>
@@ -98,6 +100,11 @@ public void SetException(Exception e)
98100
[StructLayout(LayoutKind.Auto)]
99101
public struct SpawningAsyncTaskMethodBuilder()
100102
{
103+
internal static readonly ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter Awaiter = new ValueTask(new SpecialCallbackDetector(), 0).ConfigureAwait(false).GetAwaiter();
104+
105+
[ThreadStatic]
106+
private static (Action<object?> WorkItem, object? State) capturedArgs;
107+
101108
private AsyncTaskMethodBuilder builder = AsyncTaskMethodBuilder.Create();
102109

103110
/// <summary>
@@ -114,8 +121,9 @@ public struct SpawningAsyncTaskMethodBuilder()
114121
public void Start<TStateMachine>(ref TStateMachine stateMachine)
115122
where TStateMachine : IAsyncStateMachine
116123
{
117-
var awaiter = Task.Yield().GetAwaiter();
124+
var awaiter = Awaiter;
118125
builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
126+
Schedule();
119127
}
120128

121129
/// <summary>
@@ -167,4 +175,23 @@ public void SetException(Exception e)
167175
/// Gets the task representing the builder's asynchronous operation.
168176
/// </summary>
169177
public Task Task => builder.Task;
178+
179+
internal static void Schedule()
180+
{
181+
var (continuation, state) = capturedArgs;
182+
capturedArgs = default;
183+
ThreadPool.UnsafeQueueUserWorkItem(continuation, state, preferLocal: false);
184+
}
185+
186+
private sealed class SpecialCallbackDetector : IValueTaskSource
187+
{
188+
void IValueTaskSource.GetResult(short token)
189+
{
190+
}
191+
192+
ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) => ValueTaskSourceStatus.Pending;
193+
194+
void IValueTaskSource.OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
195+
=> capturedArgs = (continuation, state);
196+
}
170197
}

0 commit comments

Comments
 (0)