+++ /dev/null
-// 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;
-using System.Diagnostics;
-using System.Threading;
-
-namespace System.Runtime.CompilerServices
-{
- internal static partial class AsyncMethodBuilder
- {
- /// <summary>Initiates the builder's execution with the associated state machine.</summary>
- /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
- /// <param name="stateMachine">The state machine instance, passed by reference.</param>
- [DebuggerStepThrough]
- public static void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
- {
- if (stateMachine == null) // TStateMachines are generally non-nullable value types, so this check will be elided
- {
- ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine);
- }
-
- // enregistrer variables with 0 post-fix so they can be used in registers without EH forcing them to stack
- // Capture references to Thread Contexts
- Thread currentThread0 = Thread.CurrentThread;
- Thread currentThread = currentThread0;
- ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext;
-
- // Store current ExecutionContext and SynchronizationContext as "previousXxx".
- // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext
- // so that they won't "leak" out of the first await.
- ExecutionContext previousExecutionCtx = previousExecutionCtx0;
- SynchronizationContext previousSyncCtx = currentThread0.SynchronizationContext;
-
- try
- {
- stateMachine.MoveNext();
- }
- finally
- {
- // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack
- SynchronizationContext previousSyncCtx1 = previousSyncCtx;
- Thread currentThread1 = currentThread;
- // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
- if (previousSyncCtx1 != currentThread1.SynchronizationContext)
- {
- // Restore changed SynchronizationContext back to previous
- currentThread1.SynchronizationContext = previousSyncCtx1;
- }
-
- ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
- ExecutionContext currentExecutionCtx1 = currentThread1.ExecutionContext;
- if (previousExecutionCtx1 != currentExecutionCtx1)
- {
- // Restore changed ExecutionContext back to previous
- currentThread1.ExecutionContext = previousExecutionCtx1;
- if ((currentExecutionCtx1 != null && currentExecutionCtx1.HasChangeNotifications) ||
- (previousExecutionCtx1 != null && previousExecutionCtx1.HasChangeNotifications))
- {
- // There are change notifications; trigger any affected
- ExecutionContext.OnValuesChanged(currentExecutionCtx1, previousExecutionCtx1);
- }
- }
- }
- }
- }
-}
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
- AsyncMethodBuilder.Start(ref stateMachine);
+ AsyncMethodBuilderCore.Start(ref stateMachine);
/// <summary>Associates the builder with the state machine it represents.</summary>
/// <param name="stateMachine">The heap-allocated state machine object.</param>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
- AsyncMethodBuilder.Start(ref stateMachine);
+ AsyncMethodBuilderCore.Start(ref stateMachine);
/// <summary>Associates the builder with the state machine it represents.</summary>
/// <param name="stateMachine">The heap-allocated state machine object.</param>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
- AsyncMethodBuilder.Start(ref stateMachine);
+ AsyncMethodBuilderCore.Start(ref stateMachine);
/// <summary>Associates the builder with the state machine it represents.</summary>
/// <param name="stateMachine">The heap-allocated state machine object.</param>
/// <summary>Shared helpers for manipulating state related to async state machines.</summary>
internal static class AsyncMethodBuilderCore // debugger depends on this exact name
{
+ /// <summary>Initiates the builder's execution with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ [DebuggerStepThrough]
+ public static void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
+ {
+ if (stateMachine == null) // TStateMachines are generally non-nullable value types, so this check will be elided
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine);
+ }
+
+ // enregistrer variables with 0 post-fix so they can be used in registers without EH forcing them to stack
+ // Capture references to Thread Contexts
+ Thread currentThread0 = Thread.CurrentThread;
+ Thread currentThread = currentThread0;
+ ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext;
+
+ // Store current ExecutionContext and SynchronizationContext as "previousXxx".
+ // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext
+ // so that they won't "leak" out of the first await.
+ ExecutionContext previousExecutionCtx = previousExecutionCtx0;
+ SynchronizationContext previousSyncCtx = currentThread0.SynchronizationContext;
+
+ try
+ {
+ stateMachine.MoveNext();
+ }
+ finally
+ {
+ // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack
+ SynchronizationContext previousSyncCtx1 = previousSyncCtx;
+ Thread currentThread1 = currentThread;
+ // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
+ if (previousSyncCtx1 != currentThread1.SynchronizationContext)
+ {
+ // Restore changed SynchronizationContext back to previous
+ currentThread1.SynchronizationContext = previousSyncCtx1;
+ }
+
+ ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
+ ExecutionContext currentExecutionCtx1 = currentThread1.ExecutionContext;
+ if (previousExecutionCtx1 != currentExecutionCtx1)
+ {
+ // Restore changed ExecutionContext back to previous
+ currentThread1.ExecutionContext = previousExecutionCtx1;
+ if ((currentExecutionCtx1 != null && currentExecutionCtx1.HasChangeNotifications) ||
+ (previousExecutionCtx1 != null && previousExecutionCtx1.HasChangeNotifications))
+ {
+ // There are change notifications; trigger any affected
+ ExecutionContext.OnValuesChanged(currentExecutionCtx1, previousExecutionCtx1);
+ }
+ }
+ }
+ }
+
/// <summary>Gets whether we should be tracking async method completions for eventing.</summary>
internal static bool TrackAsyncMethodCompletion
{