public static ClrInstance[] TryResolveContinuations(ClrInstance continuation, CausalityContext context)
        {
            if (continuation.IsListOfObjects())
            {
                var result = new List <ClrInstance>();
                int size   = (int)continuation["_size"].Instance.ValueOrDefault !;
                var items  = continuation["_items"].Instance.Items;

                for (int i = 0; i < size; i++)
                {
                    var continuationItem = TryResolveContinuationInstance(items[i], context);
                    if (continuationItem != null)
                    {
                        result.Add(continuationItem);
                    }

                    return(result.ToArray());
                }
            }

            var resolvedContinuation = TryResolveContinuationInstance(continuation, context);

            if (resolvedContinuation != null)
            {
                return(new[] { resolvedContinuation });
            }

            return(Array.Empty <ClrInstance>());
        }
Exemple #2
0
        protected CausalityNode(CausalityContext context, ClrInstance clrInstance, NodeKind kind)
        {
            Context     = context;
            ClrInstance = clrInstance;

            Id   = Contract.AssertNotNull(clrInstance.ValueOrDefault?.ToString(), "ValueOrDefault should not be null");
            Kind = kind;
        }
Exemple #3
0
        public void AddInstance(ClrInstance instance)
        {
            _instances.Add(instance);

            if (instance.ObjectAddress != null)
            {
                _instancesByAddress[instance.ObjectAddress.Value] = instance;
            }
        }
Exemple #4
0
        public bool TryGetNodeFor(ClrInstance instance, [NotNullWhen(true)] out CausalityNode?result)
        {
            if (instance.ObjectAddress != null)
            {
                return(_nodesByAddress.TryGetValue(instance.ObjectAddress.Value, out result));
            }

            result = null;
            return(false);
        }
Exemple #5
0
        public CausalityNode GetOrCreate(ClrInstance instance, NodeKind kind)
        {
            if (instance.ObjectAddress == null)
            {
                throw new InvalidOperationException($"instance.ObjectAddress should not be null. Instance: {instance}.");
            }

            //var node = _nodes.GetOrAdd(instance, task => new CausalityNode(this, task, kind: kind));
            //_nodesByAddress.GetOrAdd(node.TaskInstance.ObjectAddress.Value, node);
            var node = _nodesByAddress.GetOrAdd(instance.ObjectAddress.Value, _ => CausalityNode.Create(this, instance, kind: kind));

            return(node);
        }
Exemple #6
0
 public static CausalityNode Create(CausalityContext context, ClrInstance clrInstance, NodeKind kind)
 {
     return(kind switch
     {
         NodeKind.Task => new TaskNode(context, clrInstance),
         NodeKind.TaskCompletionSource => new TaskCompletionSourceNode(context, clrInstance),
         NodeKind.AsyncStateMachine => new AsyncStateMachineNode(context, clrInstance),
         NodeKind.AwaitTaskContinuation => new AwaitTaskContinuationNode(context, clrInstance),
         NodeKind.Thread => new ThreadNode(context, clrInstance),
         NodeKind.ManualResetEventSlim => new ManualResetEventSlimNode(context, clrInstance),
         NodeKind.SemaphoreSlim => new SemaphoreSlimNode(context, clrInstance),
         NodeKind.SynchronizationContext => new SynchronizationContextNode(context, clrInstance),
         _ => Return(() => new CausalityNode(context, clrInstance, kind)),
     });
Exemple #7
0
        public AsyncStateMachineNode(CausalityContext context, ClrInstance clrInstance)
            : base(context, clrInstance, NodeKind.AsyncStateMachine)
        {
            _status = StateMachineState switch
            {
                InitialState => StateMachineStatus.Created,
                CompletedState => StateMachineStatus.Completed,
                _ => StateMachineStatus.Awaiting,
            };

            if (_status == StateMachineStatus.Awaiting)
            {
                _awaitedTask = GetAwaitedTask();
                Contract.AssertNotNull(_awaitedTask, $"For state machine state '{StateMachineState}' an awaited task should be available");
            }

            _resultingTask = GetResultingTask(clrInstance, Context.Registry);
        }
Exemple #8
0
        public override void Link()
        {
            if (TaskKind == TaskKind.WhenAll)
            {
                foreach (var item in WhenAllContinuations)
                {
                    AddDependency(item);
                }
            }

            var parent = ClrInstance.TryGetFieldValue("m_parent")?.Instance;

            if (parent.IsNotNull())
            {
                // m_parent is not null for Parallel.ForEach, for instance.
                AddDependent(parent);
            }

            // The continuation instance is a special (causality) node, then just adding the edge
            // without extra processing.
            if (Context.TryGetNodeFor(ContinuationObject, out var dependentNode))
            {
                AddDependent(dependentNode);
            }
            else
            {
                var continuations = ContinuationResolver.TryResolveContinuations(ContinuationObject, Context);
                foreach (var c in continuations)
                {
                    // TODO: need to add an adge name for visualization purposes!
                    // Tasks created with 'ContinueWith' are different from other continuations.
                    // In this case they're dependencies not dependents.
                    if (Context.Registry.IsContinuationTaskFromTask(c))
                    {
                        AddDependency(c);
                    }
                    else
                    {
                        AddDependent(c);
                    }
                }
            }
        }
        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);
        }
        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);
        }
Exemple #11
0
        public CausalityNode GetNode(ClrInstance instance)
        {
            Contract.AssertNotNull(instance.ObjectAddress);

            return(_nodesByAddress.GetOrAdd(instance.ObjectAddress.Value, task => CausalityNode.Create(this, instance, kind: NodeKind.Unknown)));
        }
Exemple #12
0
 public SynchronizationContextNode(CausalityContext context, ClrInstance clrInstance)
     : base(context, clrInstance, NodeKind.SynchronizationContext)
 {
 }
 public AwaitTaskContinuationNode(CausalityContext context, ClrInstance clrInstance)
     : base(context, clrInstance, NodeKind.AwaitTaskContinuation)
 {
 }
Exemple #14
0
 public ManualResetEventSlimNode(CausalityContext context, ClrInstance clrInstance)
     : base(context, clrInstance, NodeKind.ManualResetEventSlim)
 {
 }
Exemple #15
0
 public bool TryGetInstanceAt(ulong address, out ClrInstance result)
 {
     return(_instancesByAddress.TryGetValue(address, out result));
 }
Exemple #16
0
 public TaskInstance(ClrInstance instance)
 {
     _instance = instance;
 }
Exemple #17
0
 public SemaphoreSlimNode(CausalityContext context, ClrInstance clrInstance) : base(context, clrInstance, NodeKind.SemaphoreSlim)
 {
     _asyncWaiters = GetAsynchronousWaiters().ToList();
 }
Exemple #18
0
 public TaskNode(CausalityContext context, ClrInstance clrInstance)
     : base(context, clrInstance, NodeKind.Task)
 {
     _taskInstance = new TaskInstance(clrInstance);
 }
 public TaskCompletionSourceNode(CausalityContext context, ClrInstance clrInstance)
     : base(context, clrInstance, NodeKind.TaskCompletionSource)
 {
 }