This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1e864d0
commit 5f15a18
Showing
2 changed files
with
78 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...stem.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Runtime.InteropServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
/// <summary>Represents a builder for asynchronous iterators.</summary> | ||
[StructLayout(LayoutKind.Auto)] | ||
public struct AsyncIteratorMethodBuilder | ||
{ | ||
// AsyncIteratorMethodBuilder is used by the language compiler as part of generating | ||
// async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as | ||
// most of the logic is shared. However, in the future this could be changed and | ||
// optimized. For example, we do need to allocate an object (once) to flow state like | ||
// ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by | ||
// allocating a Task-derived object. We could optimize this further by removing | ||
// the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations | ||
// related to it, so we'd need to replicate all of those optimizations (e.g. storing | ||
// that box object directly into a Task's continuation field). | ||
|
||
private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly | ||
|
||
/// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary> | ||
/// <returns>The initialized instance.</returns> | ||
public static AsyncIteratorMethodBuilder Create() => | ||
#if CORERT | ||
// corert's AsyncTaskMethodBuilder.Create() currently does additional debugger-related | ||
// work, so we need to delegate to it. | ||
new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() }; | ||
#else | ||
default; // coreclr's AsyncTaskMethodBuilder.Create just returns default as well | ||
#endif | ||
|
||
/// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext."/></summary> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="stateMachine">The state machine instance, passed by reference.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public void MoveNext<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine => | ||
#if CORERT | ||
_methodBuilder.Start(ref stateMachine); | ||
#else | ||
AsyncMethodBuilderCore.Start(ref stateMachine); | ||
#endif | ||
|
||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary> | ||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="awaiter">The awaiter.</param> | ||
/// <param name="stateMachine">The state machine.</param> | ||
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : INotifyCompletion | ||
where TStateMachine : IAsyncStateMachine => | ||
_methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine); | ||
|
||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary> | ||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="awaiter">The awaiter.</param> | ||
/// <param name="stateMachine">The state machine.</param> | ||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : ICriticalNotifyCompletion | ||
where TStateMachine : IAsyncStateMachine => | ||
_methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); | ||
|
||
/// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary> | ||
public void Complete() => | ||
_methodBuilder.SetResult(); | ||
|
||
/// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary> | ||
internal object ObjectIdForDebugger => | ||
_methodBuilder.ObjectIdForDebugger; | ||
} | ||
} |