From 8de665853f780afe1b62728ad56f66e213676369 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 15 Oct 2018 22:00:16 -0400 Subject: [PATCH] Add AsyncIteratorMethodBuilder Commit migrated from https://github.com/dotnet/coreclr/commit/3fc28194a4eefd6bcbb136389e807b33942265b9 --- .../src/System.Private.CoreLib.Shared.projitems | 1 + .../CompilerServices/AsyncIteratorMethodBuilder.cs | 75 ++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 5530742..cbfb463 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -426,6 +426,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs new file mode 100644 index 0000000..7a44155 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs @@ -0,0 +1,75 @@ +// 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 +{ + /// Represents a builder for asynchronous iterators. + [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 + + /// Creates an instance of the struct. + /// The initialized instance. + 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 + + /// Invokes on the state machine while guarding the + /// The type of the state machine. + /// The state machine instance, passed by reference. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void MoveNext(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine => +#if CORERT + _methodBuilder.Start(ref stateMachine); +#else + AsyncMethodBuilderCore.Start(ref stateMachine); +#endif + + /// Schedules the state machine to proceed to the next action when the specified awaiter completes. + /// The type of the awaiter. + /// The type of the state machine. + /// The awaiter. + /// The state machine. + public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : INotifyCompletion + where TStateMachine : IAsyncStateMachine => + _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine); + + /// Schedules the state machine to proceed to the next action when the specified awaiter completes. + /// The type of the awaiter. + /// The type of the state machine. + /// The awaiter. + /// The state machine. + public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) + where TAwaiter : ICriticalNotifyCompletion + where TStateMachine : IAsyncStateMachine => + _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); + + /// Marks iteration as being completed, whether successfully or otherwise. + public void Complete() => _methodBuilder.SetResult(); + + /// Gets an object that may be used to uniquely identify this builder to the debugger. + internal object ObjectIdForDebugger => _methodBuilder.ObjectIdForDebugger; + } +} -- 2.7.4