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

Commit

Permalink
Shrink AsyncValueTaskMethodBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
benaadams committed Jun 5, 2019
1 parent d888c56 commit 3568171
Show file tree
Hide file tree
Showing 5 changed files with 520 additions and 431 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace System.Runtime.CompilerServices
{
Expand All @@ -12,29 +13,29 @@ namespace System.Runtime.CompilerServices
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
// async iterators. For now, the implementation just forwards to AsyncMethodBuilderCore,
// 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
// ExecutionContext, which AsyncMethodBuilderCore 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>The lazily-initialized built task.</summary>
private Task<VoidTaskResult> m_task; // Debugger depends on the exact name of this field.

/// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary>
/// <returns>The initialized instance.</returns>
public static AsyncIteratorMethodBuilder Create() =>
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() };
var result = new AsyncIteratorMethodBuilder();
return AsyncMethodBuilderCore.InitalizeTaskIfDebugging(ref result, ref result.m_task!); // TODO-NULLABLE: Remove ! when nullable attributes are respected
#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;
return 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>
Expand All @@ -50,8 +51,8 @@ public struct AsyncIteratorMethodBuilder
/// <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);
where TStateMachine : IAsyncStateMachine
=> AsyncMethodBuilderCore.AwaitOnCompleted(ref awaiter, ref stateMachine, ref m_task);

/// <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>
Expand All @@ -60,13 +61,13 @@ public struct AsyncIteratorMethodBuilder
/// <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);
where TStateMachine : IAsyncStateMachine
=> AsyncMethodBuilderCore.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine, ref m_task);

/// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary>
public void Complete() => _methodBuilder.SetResult();
public void Complete() => AsyncMethodBuilderCore.SetResult(ref m_task, Task.s_cachedCompleted);

/// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary>
internal object ObjectIdForDebugger => _methodBuilder.ObjectIdForDebugger;
internal object ObjectIdForDebugger => AsyncMethodBuilderCore.ObjectIdForDebugger(ref m_task);
}
}
Loading

0 comments on commit 3568171

Please sign in to comment.