Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Add AsyncIteratorMethodBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
stephentoub committed Oct 19, 2018
1 parent 1e864d0 commit 5f15a18
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\SatelliteContractVersionAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\UltimateResourceFallbackLocation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AccessedThroughPropertyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncIteratorMethodBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncStateMachineAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs" />
Expand Down
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;
}
}

0 comments on commit 5f15a18

Please sign in to comment.