public static ClrInstance?TryResolveContinuationInstance(ClrInstance continuation, CausalityContext context) { if (continuation.IsOfType(context.Registry.StandardTaskContinuationType)) { return(continuation["m_task"].Instance); } if (continuation.IsTaskCompletionSource(context)) { return(continuation["m_task"].Instance); } if (continuation.IsCompletedTaskContinuation(context)) { // Continuation is a special sentinel instance that indicates that the task is completed. return(null); } if (continuation.IsOfType(typeof(Action), context)) { return(TryResolveContinuationForAction(continuation, context)); } if (continuation.IsOfType(context.Registry.AwaitTaskContinuationIndex) || continuation.IsOfType(context.Registry.TaskIndex)) { return(TryResolveContinuationForAction(continuation["m_action"].Instance, context)); } // Need to compare by name since GetTypeByName does not work for the generic type during initialization if (continuation.IsListOfObjects()) { Contract.Assert(false, "Please call 'TryResolveContinuations' for a list of continuations."); } return(null); }
public static ClrInstance?TryResolveContinuationForAction(ClrInstance instance, CausalityContext context) { Contract.Requires(instance.IsOfType(typeof(Action), context), $"A given instance should be of type System.Action, but was '{instance.Type.TypeToString(context.Registry)}'"); var continuation = instance; var actionTarget = continuation["_target"].Instance; if (actionTarget.IsOfType(context.Registry.ContinuationWrapperType)) { // Do we need to look at the m_innerTask field as well here? return(actionTarget["m_continuation"].Instance); } // If the action points to a closure, it is possible that the closure // is responsible for setting the result of a task completion source. // There is no simple way to detect whether this is the case or not, so we will add the "edge" unconditionally. if (actionTarget.Type.IsClosure()) { foreach (var field in actionTarget.Fields) { if (field.Instance.IsTaskCompletionSource(context)) { return(field.Instance); } } } // m_stateMachine field is defined in AsyncMethodBuilderCore and in MoveNextRunner. var stateMachine = actionTarget.TryGetFieldValue("m_stateMachine")?.Instance; if (stateMachine.IsNull()) { return(null); } return(stateMachine); }