private bool AreTheSameStateMachines(IAsyncStateMachine asm1, IAsyncStateMachine asm2)
        {
            if (ReferenceEquals(asm1, asm2))
            {
                return(true);
            }

            if (asm1.GetType() != asm2.GetType())
            {
                return(false);
            }

            // WARNING!
            // In RELEASE mode a state machine is compiled into a values type, not reference type!
            // The builder is also is a value type, so the only way to say exactly is to compare
            // the completion Tasks, which are always reference types.
            if (asm1.GetType().IsValueType())
            {
#warning Optimize this code, don't inject IAsyncStateMachineMetadataProvider into this class.
                var metadata        = _asyncStateMachineMetadataProvider.GetMetadata(asm1.GetType());
                var builder1        = metadata.Builder.FieldInfo.GetValue(asm1);
                var builder2        = metadata.Builder.FieldInfo.GetValue(asm2);
                var taskField       = metadata.Builder.FieldInfo.FieldType.GetProperty("Task");
                var completionTask1 = taskField.GetValue(builder1);
                var completionTask2 = taskField.GetValue(builder2);
                return(ReferenceEquals(completionTask1, completionTask2));
            }

            return(false);
        }
Example #2
0
 public DistributionAble(IAsyncStateMachine sm)
 {
     clone = (distributionAtor) =>
     {
         var memberwiseCloneMethod = sm.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
         var builderField          = sm.GetType().GetField("<>t__builder", BindingFlags.Instance | BindingFlags.Public);
         var clone = (IAsyncStateMachine)memberwiseCloneMethod.Invoke(sm, null);
         builderField.SetValue(clone, new DistributionBuilder <T> {
             _DistributionAtor = distributionAtor
         });
         return(clone);
     };
 }
Example #3
0
 public Sampleable(IAsyncStateMachine sm)
 {
     clone = (Sampler) =>
     {
         var memberwiseCloneMethod = sm.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
         var builderField          = sm.GetType().GetField("<>t__builder", BindingFlags.Instance | BindingFlags.Public);
         var clone = (IAsyncStateMachine)memberwiseCloneMethod.Invoke(sm, null);
         builderField.SetValue(clone, new SampleableBuilder <T> {
             _Sampler = Sampler
         });
         return(clone);
     };
 }
Example #4
0
    static async Task AsyncMethod()
    {
        int x = 10;
        IAsyncStateMachine machine = await StateMachineProvider.GetStateMachine();

        Console.WriteLine(x);
        Console.WriteLine($"State machine type: {machine.GetType()})");
        Console.WriteLine("Fields:");
        foreach (var field in machine.GetType()
                 .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            Console.WriteLine($"{field.Name}: {field.GetValue(machine)}");
        }
    }
Example #5
0
    static async Task AsyncMethod()
    {
        int x = 10;
        IAsyncStateMachine machine = await StateMachineProvider.GetStateMachine();

        Console.WriteLine($"x={x}");     // Force the use across an await boundary
        Console.WriteLine($"State machine type: {machine.GetType()})");
        Console.WriteLine("Fields:");
        var fields = machine.GetType().GetFields(Public | NonPublic | Instance);

        foreach (var field in fields)
        {
            Console.WriteLine($"{field.Name}: {field.GetValue(machine)}");
        }
    }
        public static Member <int> GetCurrentStateNumber(this IAsyncStateMachine sm)
        {
            var fieldInfo = sm.GetType().GetField("<>1__state");
            var value     = (int)fieldInfo.GetValue(sm);

            return(CreateMember(fieldInfo.Name, value));
        }
Example #7
0
        public static string Describe(object box)
        {
            if (box is null)
            {
                return("(Couldn't get state machine box.)");
            }

            FieldInfo stateMachineField = box.GetType().GetField("StateMachine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            if (stateMachineField is null)
            {
                return($"(Couldn't get state machine field from {box}.");
            }

            IAsyncStateMachine stateMachine = stateMachineField.GetValue(box) as IAsyncStateMachine;

            if (stateMachine is null)
            {
                return($"(Null state machine from {box}.)");
            }

            Type stateMachineType = stateMachine.GetType();

            FieldInfo[] fields = stateMachineType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            var sb = new StringBuilder();

            sb.AppendLine(stateMachineType.FullName);
            foreach (FieldInfo fi in fields)
            {
                sb.AppendLine($"    {fi.Name}: {ToString(fi.GetValue(stateMachine))}");
            }
            return(sb.ToString());
        }
Example #8
0
            private void SetTCS(IAsyncStateMachine machine, TaskCompletionSource <T> tcs)
            {
                // Option 1: (works only in release mode)
                // TODO: measure if it is any faster
                tcsGlobalSignal = tcs;
                machine.SetStateMachine(machine);
                if (tcsGlobalSignal is object)
                {
                    IOTaskMethodBuilder <T> newBuilder;
                    newBuilder.preboxedMachine = machine;
                    newBuilder.tcs             = tcs;
                    newBuilder.boxedMoveNext   = null;
                    newBuilder.resultIO        = this;
                    // TODO: add preboxed machine

                    tcsGlobalSignal = null;

                    machine.GetType().GetField("<>t__builder").SetValue(machine, newBuilder);

                    // // Using DLR
                    // // https://sharplab.io/#v2:D4AQTAjAsAULBuBDATgAgCaoLyoHYFMB3DAFgAoBKAblgGEA6AWTPQBoN8AzRAVwBsALtVjp6ASVwBnAA74AxgMo04MSfkR98mcKVgBvWAEgQAZlQBLXANSSBiAfmWxUL1KdSMAngGUByHgqoAgBGPOZ86PjIyq6osAC+sLC2/oFevqnWBjCx7pbWAB7KiSo6tKjZsW5mIBAAbG4kHmQA8sEAVvLWiOzpfgGFFBXOVbFkLJ64iAC25nIUiBT0IWERUdioRSOuJfFAA==

                    // if (callSiteCache is null)
                    // {
                    //     Type context = typeof(BuiltIO);
                    //     var args = new CSharpArgumentInfo[] {
                    //         CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                    //         CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)
                    //     };

                    //     callSiteCache = CallSite<Func<CallSite, object, IOTaskMethodBuilder<T>, object>>.Create(Microsoft.CSharp.RuntimeBinder.Binder.SetMember(CSharpBinderFlags.None, "<>t__builder", context, args));
                    // }
                    // callSiteCache.Target(callSiteCache, machine, newBuilder);
                }
            }
Example #9
0
        // Get AsyncStateMachine internal state to check IL2CPP bug
        public static int GetState(IAsyncStateMachine stateMachine)
        {
            var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                       .First(x => x.Name.EndsWith("__state"));

            return((int)info.GetValue(stateMachine));
        }
Example #10
0
        /// <summary>
        /// The field names of "async state machine" are not fixed; the workaround is to find the field based on the suffix.
        /// </summary>
        private static object GetStateMachineFieldValueOnSuffix(IAsyncStateMachine stateMachine, string suffix)
        {
            Requires.NotNull(stateMachine, nameof(stateMachine));
            Requires.NotNullOrEmpty(suffix, nameof(suffix));

            var fields = stateMachine.GetType().GetTypeInfo().DeclaredFields;
            var field  = fields.FirstOrDefault((f) => f.Name.EndsWith(suffix, StringComparison.Ordinal));

            if (field != null)
            {
                return(field.GetValue(stateMachine));
            }

            return(null);
        }
Example #11
0
            private void Initialize(Action continuation, IAsyncStateMachine stateMachine, IAsyncOperation asyncOperation)
            {
                const MemberFlags flags = MemberFlags.NonPublic | MemberFlags.Public | MemberFlags.Instance;

                if (stateMachine == null)
                {
                    stateMachine = continuation.Target as IAsyncStateMachine;
                    if (stateMachine == null)
                    {
                        var fieldInfo = continuation.Target
                                        .GetType()
                                        .GetFieldEx("m_continuation", flags);
                        if (fieldInfo != null)
                        {
                            continuation = fieldInfo.GetValueEx <Action>(continuation.Target);
                        }

                        fieldInfo = continuation.Target
                                    .GetType()
                                    .GetFieldEx("m_stateMachine", flags);
                        if (fieldInfo == null)
                        {
                            TraceError(continuation.Target);
                            return;
                        }
                        stateMachine = fieldInfo.GetValueEx <IAsyncStateMachine>(continuation.Target);
                        if (stateMachine == null)
                        {
                            TraceError(continuation.Target);
                            return;
                        }
                    }
                }
                var type = stateMachine.GetType();

                StateMachineType = type.AssemblyQualifiedName;
                FieldSnapshots   = new List <FieldSnapshot>();

                foreach (var field in type.GetFieldsEx(flags))
                {
                    var snapshot = FieldSnapshot.Create(field, stateMachine, asyncOperation);
                    if (snapshot != null)
                    {
                        FieldSnapshots.Add(snapshot);
                    }
                }
            }
Example #12
0
        static string Name(this IAsyncStateMachine sm)
        {
            var t = sm.GetType();
            var s = t.Name;

            s = s.Substring(1, s.LastIndexOf(">") - 1);
            while (true)
            {
                t = t.DeclaringType;
                if (t != null)
                {
                    s = t.Name + "." + s;
                }
                else
                {
                    return(s + $" [task id {sm.Task()?.Id}]");
                }
            }
        }
Example #13
0
        public static IEnumerable <Member <object> > GetLocalsAndParameters(this IAsyncStateMachine sm)
        {
            var fieldInfos = sm.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var fieldInfo in fieldInfos)
            {
                if (fieldInfo.Name == "<>t__builder")
                {
                    continue;                                   // builder
                }
                if (fieldInfo.Name.StartsWith("<>u__"))
                {
                    continue;                                     // awaiters
                }
                if (fieldInfo.Name == "<>1__state")
                {
                    continue;                                 // state
                }
                // all other fields are locals and parameters
                var value = fieldInfo.GetValue(sm);
                yield return(CreateMember(fieldInfo.Name, value));
            }
        }
Example #14
0
        public static Member <object> GetCurrentAwaiter(this IAsyncStateMachine sm)
        {
            var candidateAwaiters = new List <Member <object> >();

            var fieldInfos = sm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var fieldInfo in fieldInfos)
            {
                if (!fieldInfo.Name.StartsWith("<>u__"))
                {
                    continue;
                }
                var awaiter = fieldInfo.GetValue(sm); if (awaiter == null)
                {
                    continue;
                }

                // typical awaiters have a field named "m_task" of type Task
                var taskFieldInfo = awaiter.GetType().GetField("m_task", BindingFlags.NonPublic | BindingFlags.Instance);
                if (taskFieldInfo != null && typeof(Task).IsAssignableFrom(taskFieldInfo.FieldType))
                {
                    var m_task = taskFieldInfo.GetValue(awaiter);
                    if (m_task == null)
                    {
                        continue;
                    }
                }

                candidateAwaiters.Add(CreateMember(fieldInfo.Name, awaiter));
            }

            if (candidateAwaiters.Count != 1)
            {
                throw new NotSupportedException($"Async method {sm.Name()} has awaiters that are too complicated to process");
            }
            return(candidateAwaiters[0]);
        }
Example #15
0
        private bool TryFindDelayPromise(
            IAsyncStateMachine stateMachine,
            out Task delayPromise)
        {
#warning such analysis can be optimizer by pre-compiling the code per state machine type
            var metadata = _asyncStateMachineMetadataProvider.GetMetadata(stateMachine.GetType());

            foreach (var variable in metadata.LocalVariables)
            {
                if (TaskAwaiterUtils.IsAwaiterType(variable.FieldInfo.FieldType))
                {
                    var awaiter = variable.FieldInfo.GetValue(stateMachine);
                    var task    = TaskAwaiterUtils.GetTask(awaiter);
                    if (task != null && DelayPromiseAccessor.IsDelayPromise(task))
                    {
                        delayPromise = task;
                        return(true);
                    }
                }
            }

            delayPromise = null;
            return(false);
        }
Example #16
0
 private static FieldInfo BuilderField(this IAsyncStateMachine sm) => sm.GetType().GetField("<>t__builder") ?? sm.GetType().GetField("$Builder");
Example #17
0
 // Token: 0x06005D16 RID: 23830 RVA: 0x001465B8 File Offset: 0x001447B8
 internal void PostBoxInitialization(IAsyncStateMachine stateMachine, AsyncMethodBuilderCore.MoveNextRunner runner, Task builtTask)
 {
     if (builtTask != null)
     {
         if (AsyncCausalityTracer.LoggingOn)
         {
             AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, builtTask.Id, "Async: " + stateMachine.GetType().Name, 0UL);
         }
         if (Task.s_asyncDebuggingEnabled)
         {
             Task.AddToActiveTasks(builtTask);
         }
     }
     this.m_stateMachine = stateMachine;
     this.m_stateMachine.SetStateMachine(this.m_stateMachine);
     runner.m_stateMachine = this.m_stateMachine;
 }
 private string ExtractStateMachineName(IAsyncStateMachine generatedStateMachine)
 => generatedStateMachine.GetType()
 .Name
 .Split(new string[] { ">" }, StringSplitOptions.RemoveEmptyEntries)[0]
 .Replace("<", "");
Example #19
0
            static void Describe(object box, StringBuilder sb, HashSet <object> seen, int indentLevel)
            {
                string indent = string.Concat(Enumerable.Repeat("    ", indentLevel));

                // If we were handed a null object (which should only happen from recursion),
                // state that the object was null.
                if (box is null)
                {
                    sb.Append(indent).AppendLine($"(Object was null.)");
                    return;
                }

                // If as we're walking a graph we happen upon a cycle, break it.
                if (!seen.Add(box))
                {
                    sb.Append(indent).AppendLine($"(Object already seen in graph walk.)");
                    return;
                }

                // Try to get the StateMachine field from the AsyncStateMachineBox<>.  If we can't,
                // just print out the details we can and bail.
                FieldInfo stateMachineField = box.GetType().GetField("StateMachine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

                if (stateMachineField is null)
                {
                    sb.Append(indent).AppendLine($"(Couldn't get state machine field from {box}.)");
                    sb.Append(indent).AppendLine(ToString(box));
                    return;
                }

                // Get the state machine from the StateMachine field.
                IAsyncStateMachine stateMachine = stateMachineField.GetValue(box) as IAsyncStateMachine;

                if (stateMachine is null)
                {
                    sb.Append(indent).AppendLine($"(Null state machine from {box}.)");
                    return;
                }

                // Print out the name of the state machine.
                Type stateMachineType = stateMachine.GetType();

                sb.Append(indent).AppendLine(stateMachineType.FullName);

                // Get all of the fields on the state machine, and print them all out.
                FieldInfo[] fields = stateMachineType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                foreach (FieldInfo fi in fields)
                {
                    // Print out the field name and its value.
                    object fiValue = fi.GetValue(stateMachine);
                    sb.Append(indent).AppendLine($"  {fi.Name}: {ToString(fiValue)}");

                    // If the field is an awaiter, recursively examine any tasks it directly references.
                    if (fiValue is ICriticalNotifyCompletion)
                    {
                        foreach (FieldInfo possibleTask in fiValue.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
                        {
                            if (possibleTask.GetValue(fiValue) is Task awaitedTask)
                            {
                                Describe(awaitedTask, sb, seen, indentLevel + 1);
                            }
                        }
                    }
                }
            }
Example #20
0
 public static bool IsCompilerGenerated(this IAsyncStateMachine asyncStateMachine)
 {
     return(asyncStateMachine.GetType().GetCustomAttribute <CompilerGeneratedAttribute>() != null);
 }
Example #21
0
 private static FieldInfo GetStateField(this IAsyncStateMachine stateMachine)
 {
     return(stateMachine.GetType().GetField("<>1__state"));
 }
 private object ExtractTarget(IAsyncStateMachine generatedStateMachine)
 => generatedStateMachine.GetType().GetFields()
 .FirstOrDefault(f => f.Name.Contains("this"))
 ?.GetValue(generatedStateMachine);
 private string ExtractClassContained(IAsyncStateMachine generatedStateMachine)
 => generatedStateMachine.GetType()
 .FullName
 .Split(new string[] { "+" }, StringSplitOptions.RemoveEmptyEntries)[0];