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); }
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); }; }
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); }; }
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)}"); } }
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)); }
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()); }
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); } }
// 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)); }
/// <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); }
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); } } }
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}]"); } } }
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)); } }
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]); }
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); }
private static FieldInfo BuilderField(this IAsyncStateMachine sm) => sm.GetType().GetField("<>t__builder") ?? sm.GetType().GetField("$Builder");
// 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("<", "");
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); } } } } }
public static bool IsCompilerGenerated(this IAsyncStateMachine asyncStateMachine) { return(asyncStateMachine.GetType().GetCustomAttribute <CompilerGeneratedAttribute>() != null); }
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];