Skip to content

Commit 435eb72

Browse files
committed
update async code
1 parent 40f02f7 commit 435eb72

File tree

4 files changed

+35
-55
lines changed

4 files changed

+35
-55
lines changed

src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public ConfiguredValueTaskAwaiter GetAwaiter() =>
3434

3535
/// <summary>Provides an awaiter for a <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
3636
[StructLayout(LayoutKind.Auto)]
37-
public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
37+
public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IValueTaskAwaiter
3838
{
3939
/// <summary>The value being awaited.</summary>
4040
private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
@@ -69,6 +69,12 @@ public void UnsafeOnCompleted(Action continuation) =>
6969

7070
/// <summary>Gets the task underlying <see cref="_value"/>.</summary>
7171
internal Task<TResult> AsTask() => _value.AsTask();
72+
73+
public Task GetTask(ref bool continueOnCapturedContent)
74+
{
75+
continueOnCapturedContent = _continueOnCapturedContext;
76+
return AsTask();
77+
}
7278
}
7379
}
7480
}

src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace System.Runtime.CompilerServices
99
{
1010
/// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
11-
public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
11+
public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, IValueTaskAwaiter
1212
{
1313
/// <summary>The value being awaited.</summary>
1414
private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
@@ -20,7 +20,7 @@ public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
2020
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> has completed.</summary>
2121
public bool IsCompleted => _value.IsCompleted;
2222

23-
/// <summary>Gets the result of the ValueTask.</summary>
23+
/// <summary>Gets the result of the ValueTask.t</summary>
2424
public TResult GetResult() =>
2525
_value._task == null ?
2626
_value._result :
@@ -36,5 +36,11 @@ public void UnsafeOnCompleted(Action continuation) =>
3636

3737
/// <summary>Gets the task underlying <see cref="_value"/>.</summary>
3838
internal Task<TResult> AsTask() => _value.AsTask();
39+
40+
public Task GetTask(ref bool continueOnCapturedContent)
41+
{
42+
continueOnCapturedContent = true;
43+
return AsTask();
44+
}
3945
}
4046
}

src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
393393
{
394394
IAsyncStateMachineBox box = GetStateMachineBox(ref stateMachine);
395395

396-
// TThe null tests here ensure that the jit can optimize away the interface
396+
// The null tests here ensure that the jit can optimize away the interface
397397
// tests when TAwaiter is is a ref type.
398398
if ((null != (object)default(TAwaiter)) && (awaiter is ITaskAwaiter))
399399
{
@@ -405,62 +405,23 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
405405
ref ConfiguredTaskAwaitable.ConfiguredTaskAwaiter ta = ref Unsafe.As<TAwaiter, ConfiguredTaskAwaitable.ConfiguredTaskAwaiter>(ref awaiter);
406406
TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, ta.m_continueOnCapturedContext);
407407
}
408-
409-
// Handle common {Configured}ValueTaskAwaiter<T> types. Unfortunately these need to be special-cased
410-
// individually, as we don't have good way to extract the task from a ValueTaskAwaiter<T> when we don't
411-
// know what the T is; we could make ValueTaskAwaiter<T> implement an IValueTaskAwaiter interface, but
412-
// calling a GetTask method on that would end up boxing the awaiter. This hard-coded list here is
413-
// somewhat arbitrary and is based on types currently in use with ValueTask<T> in coreclr/corefx.
414-
else if (typeof(TAwaiter) == typeof(ValueTaskAwaiter<int>))
415-
{
416-
var vta = (ValueTaskAwaiter<int>)(object)awaiter;
417-
TaskAwaiter.UnsafeOnCompletedInternal(vta.AsTask(), box, continueOnCapturedContext: true);
418-
}
419-
else if (typeof(TAwaiter) == typeof(ConfiguredValueTaskAwaitable<int>.ConfiguredValueTaskAwaiter))
420-
{
421-
var vta = (ConfiguredValueTaskAwaitable<int>.ConfiguredValueTaskAwaiter)(object)awaiter;
422-
TaskAwaiter.UnsafeOnCompletedInternal(vta.AsTask(), box, vta._continueOnCapturedContext);
423-
}
424-
else if (typeof(TAwaiter) == typeof(ConfiguredValueTaskAwaitable<System.IO.Stream>.ConfiguredValueTaskAwaiter))
425-
{
426-
var vta = (ConfiguredValueTaskAwaitable<System.IO.Stream>.ConfiguredValueTaskAwaiter)(object)awaiter;
427-
TaskAwaiter.UnsafeOnCompletedInternal(vta.AsTask(), box, vta._continueOnCapturedContext);
428-
}
429-
else if (typeof(TAwaiter) == typeof(ConfiguredValueTaskAwaitable<ArraySegment<byte>>.ConfiguredValueTaskAwaiter))
408+
else if ((null != (object)default(TAwaiter)) && (awaiter is IValueTaskAwaiter))
430409
{
431-
var vta = (ConfiguredValueTaskAwaitable<ArraySegment<byte>>.ConfiguredValueTaskAwaiter)(object)awaiter;
432-
TaskAwaiter.UnsafeOnCompletedInternal(vta.AsTask(), box, vta._continueOnCapturedContext);
410+
bool continueOnCapturedContent = true;
411+
Task task = ((IValueTaskAwaiter)awaiter).GetTask(ref continueOnCapturedContent);
412+
TaskAwaiter.UnsafeOnCompletedInternal(task, box, continueOnCapturedContent);
433413
}
434-
else if (typeof(TAwaiter) == typeof(ConfiguredValueTaskAwaitable<object>.ConfiguredValueTaskAwaiter))
435-
{
436-
var vta = (ConfiguredValueTaskAwaitable<object>.ConfiguredValueTaskAwaiter)(object)awaiter;
437-
TaskAwaiter.UnsafeOnCompletedInternal(vta.AsTask(), box, vta._continueOnCapturedContext);
438-
}
439-
440414
// The awaiter isn't specially known. Fall back to doing a normal await.
441415
else
442416
{
443-
// TODO https://github.com/dotnet/coreclr/issues/14177:
444-
// Move the code back into this method once the JIT is able to
445-
// elide it successfully when one of the previous branches is hit.
446-
AwaitArbitraryAwaiterUnsafeOnCompleted(ref awaiter, box);
447-
}
448-
}
449-
450-
/// <summary>Schedules the specified state machine to be pushed forward when the specified awaiter completes.</summary>
451-
/// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
452-
/// <param name="awaiter">The awaiter.</param>
453-
/// <param name="box">The state machine box.</param>
454-
private static void AwaitArbitraryAwaiterUnsafeOnCompleted<TAwaiter>(ref TAwaiter awaiter, IAsyncStateMachineBox box)
455-
where TAwaiter : ICriticalNotifyCompletion
456-
{
457-
try
458-
{
459-
awaiter.UnsafeOnCompleted(box.MoveNextAction);
460-
}
461-
catch (Exception e)
462-
{
463-
AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
417+
try
418+
{
419+
awaiter.UnsafeOnCompleted(box.MoveNextAction);
420+
}
421+
catch (Exception e)
422+
{
423+
AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
424+
}
464425
}
465426
}
466427

src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ internal interface ITaskAwaiter { }
386386
/// </summary>
387387
internal interface IConfiguredTaskAwaiter { }
388388

389+
/// <summary>
390+
/// Interface used by various ValueTaskAwaiters.
391+
/// </summary>
392+
internal interface IValueTaskAwaiter {
393+
Task GetTask(ref bool continueOnCapturedContent);
394+
}
395+
389396
/// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task"/>.</summary>
390397
/// <remarks>This type is intended for compiler use only.</remarks>
391398
public struct ConfiguredTaskAwaitable

0 commit comments

Comments
 (0)