1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- #if !BCL_HAS_CONFIGUREAWAIT
- // 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.Diagnostics;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Text;
- 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).
- #pragma warning disable IDE0044 // Add readonly modifier
- private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly
- #pragma warning restore IDE0044 // Add readonly modifier
- /// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary>
- /// <returns>The initialized instance.</returns>
- public static AsyncIteratorMethodBuilder Create() =>
- #if PROJECTN
- // ProjectN's AsyncTaskMethodBuilder.Create() currently does additional debugger-related
- // work, so we need to delegate to it.
- new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() };
- #else
- // _methodBuilder should be initialized to AsyncTaskMethodBuilder.Create(), but on coreclr
- // that Create() is a nop, so we can just return the default here.
- default;
- #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 || !BCL_HAS_CONFIGUREAWAIT
- _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 => typeof(AsyncTaskMethodBuilder)
- .GetProperty("ObjectIdForDebugger", BindingFlags.Instance | BindingFlags.NonPublic)
- .GetMethod.Invoke(_methodBuilder, null);
- }
- }
- #else
- using System.Runtime.CompilerServices;
- [assembly: TypeForwardedTo(typeof(AsyncIteratorMethodBuilder))]
- #endif
|